如何让Json.NET为具有复杂值的属性设置IsSpecified属性?

2024-01-05

我有一个使用 ASP.Net 构建的 Web 服务,到目前为止它仅使用 XML 作为输入和输出。现在它还需要能够使用 JSON。

我们使用 xsd2code++ 从 XSD 生成模型,并可以选择创建“指定”属性 https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/zds0b35c(v=vs.100)启用(即,如果在 XML 中指定了属性,则其各自的“指定”属性将是true).

从像这样的 XSD...

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="Person">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="ID" type="xs:string"/>
        <xs:element name="Details" type="PersonalDetails"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  
  
  <xs:complexType name="PersonalDetails">
    <xs:sequence>
      <xs:element name="FirstName" type="xs:string"/>
      <xs:element name="LastName" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

... xsd2code++ 创建一个类,其属性如下:

public partial class Person
{
    #region Private fields
    private string _id;
    private PersonalDetails _details;
    private Address _address;
    private bool _iDSpecified;
    private bool _detailsSpecified;
    private bool _addressSpecified;
    #endregion

    public Person()
    {
        this._address = new Address();
        this._details = new PersonalDetails();
    }

    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string ID
    {
        get
        {
            return this._id;
        }
        set
        {
            this._id = value;
        }
    }

    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public PersonalDetails Details
    {
        get
        {
            return this._details;
        }
        set
        {
            this._details = value;
        }
    }

    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public Address Address
    {
        get
        {
            return this._address;
        }
        set
        {
            this._address = value;
        }
    }

    [XmlIgnore()]
    public bool IDSpecified
    {
        get
        {
            return this._iDSpecified;
        }
        set
        {
            this._iDSpecified = value;
        }
    }

    [XmlIgnore()]
    public bool DetailsSpecified
    {
        get
        {
            return this._detailsSpecified;
        }
        set
        {
            this._detailsSpecified = value;
        }
    }

    [XmlIgnore()]
    public bool AddressSpecified
    {
        get
        {
            return this._addressSpecified;
        }
        set
        {
            this._addressSpecified = value;
        }
    }
}

这对于 XML 非常有用。 例如,如果输入 XML 中未指定 ID,则属性 IDSpecified 将为false。我们可以在业务逻辑层使用这些“指定”属性,这样我们就知道哪些数据必须插入/更新,以及哪些数据可以忽略/跳过。

然后,我们尝试添加 JSON 序列化。 我们向 WebApiConfig 类添加了一个 Json 格式化程序:

config.Formatters.Add(new JsonMediaTypeFormatter());
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();

API 现在将识别 JSON 输入,但“指定”属性无法像 XML 那样适用于复杂对象,并且始终会说它们是false.

{
    "ID": "abc123", // IDSpecified comes through as "true"
    "Details": { // DetailsSpecified always comes through as "false"
        "FirstName": "John", // FirstNameSpecified = true
        "LastName": "Doe", // LastNameSpecified = true
        "BirthDate": "1990-06-20" // BirthDateSpecified = true
    }
}

Newtonsoft 的 DefaultContractResolver 是否与这些“指定”字段不完全兼容,就像 XML 一样?我是否需要明确说明每个属性的“指定”值是否为 true? 或者我错过了什么?

EDIT: 我已经将一些示例代码上传到 GitHub:https://github.com/AndreNobrega/XML-JSON-Serialization-POC https://github.com/AndreNobrega/XML-JSON-Serialization-POC

我尝试发送的请求正文可以在项目的 Examples 文件夹中找到。 POST 请求可以发送到 .../api/Person。 发送 XML 示例时,我设置了Content-Type标头至application/xml。发送 JSON 示例时,我将其设置为application/json.

如果在 PersonController 类的 Post() 方法中设置断点,您将看到xxxSpecifiedXML 请求的成员设置正确,但 JSON 请求的成员设置不正确。

也许它与由 xsd2code++ 自动生成的 Person.Designer 类有关?该属性是否有等效的 JSON[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]?


您似乎遇到了 Json.NET 支持的限制{propertyName}Specified members https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_DefaultContractResolver_IgnoreIsSpecifiedMembers.htm: the {propertyName}Specified填充 a 的实例时未设置属性预先分配的引用类型属性。作为解决方法,您可以使用设置反序列化JsonSerializerSettings.ObjectCreationHandling = ObjectCreationHandling.Replace https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonSerializerSettings_ObjectCreationHandling.htm。如果这样做,引用类型属性的新实例将由序列化程序创建,并在创建后设置回原样,从而切换相应的{propertyName}Specified财产。

详细解释如下。在你的Person类型,您自动分配子属性的实例Address and Details在默认构造函数中:

public Person()
{
    this._address = new Address();
    this._details = new PersonalDetails();
}

现在,因为 Json.NET 支持填充现有对象 https://www.newtonsoft.com/json/help/html/PopulateObject.htm,在反序列化过程中,调用默认值之后Person()构造函数,它将填充的值Address and Details您构建的,而不是创建新的。正因为如此,它显然从不要求设置者Address and Details,也许是因为 Newtonsoft 认为没有必要这样做。但这反过来似乎又阻止了相应的Specified属性被设置,因为看起来 Json.NET 仅在调用 setter 时才切换它们。

(为了比较,XmlSerializer从不填充除集合值属性之外的预分配引用类型属性,因此这种情况不应出现XmlSerializer.)

这可能是 Json.NET 实现中的一个错误{propertyName}Specified图案。你可能想要打开一个问题 https://github.com/JamesNK/Newtonsoft.Json/issues与 Newtonsoft 联系。

演示小提琴#1here https://dotnetfiddle.net/0taaIn.

作为解决方法,您可以:

  • 使用设置反序列化JsonSerializerSettings.ObjectCreationHandling = ObjectCreationHandling.Replace https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonSerializerSettings_ObjectCreationHandling.htm像这样:

    config.Formatters.JsonFormatter.SerializerSettings.ObjectCreationHandling = ObjectCreationHandling.Replace;
    

    该选项将总是创建新对象从而触发设置Specified特性。

    演示小提琴#2here https://dotnetfiddle.net/z5L3Yq.

  • 删除分配Address and Details来自默认构造函数Person。不太推荐,但确实解决了问题。

    演示小提琴 #3here https://dotnetfiddle.net/scBVHZ.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何让Json.NET为具有复杂值的属性设置IsSpecified属性? 的相关文章

  • 在android中从JSON生成listview

    我对 Android 完全陌生 目前正在尝试从从我的服务器中提取的 JSON 数组生成列表视图 我已经阅读了很多教程 但没有运气 有一种独特的方法可以做到这一点 请您指出一些适合开始的资源 我读过了this http www josecgo
  • 将巨大的模式编译成Java

    有两个主要工具提供了将 XSD 模式编译为 Java 的方法 xmlbeans 和 JAXB 问题是 XSD 模式确实很大 30MB 的 XML 文件 大部分模式在我的项目中没有使用 所以我可以注释掉大部分代码 但这不是一个好的解决方案 目
  • 优化数据可视化 Web 应用程序的性能

    我正在重写 3 年前编写的数据可视化网络工具 从那时起 浏览器的 JavaScript 引擎变得更快 所以我正在考虑将部分工作从服务器转移到客户端 在页面上 数据在表格和地图 或图表 中可视化 它使用相同的数据 但以不同的方式 因此准备显示
  • 如何使用 Retrofit 解析嵌套 json....?

    我不知道该怎么办使用 Retrofit 解析 json 熟悉使用 Retrofit 解析简单的 json 但不熟悉解析嵌套Json using Retrofit 这是我的 Json 数据 current observation image
  • VBA XML V6.0 如何让它等待页面加载?

    我一直在努力寻找答案 但似乎找不到任何有用的东西 基本上 我是从一个网站上拉取的 当您在该页面上时 该网站会加载更多项目 我希望我的代码在加载完成后提取最终数据 但不知道如何让 XML httprequest 等待 Edited Sub p
  • Silverlight 3 工具未显示在 Visual Studio 中

    我下载并安装了Silverlight 3 工具 http go microsoft com fwlink LinkID 143571 我想在 ASP net 页面中使用 Silverlight 服务器控件 但我的工具箱中没有 Silverl
  • 如何在服务器端按钮点击时关闭当前标签页?

    我尝试在确认后关闭当前选项卡 因此我将以下代码放在确认按钮的末尾 但选项卡没有关闭 string jScript ClientScript RegisterClientScriptBlock this GetType keyClientBl
  • 使用restsharp序列化对象并将其传递给WebApi而不是序列化列表

    我有一个看起来像的视图模型 public class StoreItemViewModel public Guid ItemId get set public List
  • xsi:type 属性搞乱了 C# XML 反序列化

    我使用 XSD exe 根据 XML 架构 xsd 文件 自动生成 C 对象 我正在反序列化 OpenCover 输出 但其中一个部分类未正确生成 这是导致异常的行
  • 从 JavaScript 中的 OnClientClick 事件中阻止 C# 中的 asp:Button OnClick 事件?

    我有一个asp Button在我的网页上 它调用 JavaScript 函数和代码隐藏方法 后者进行调用以导航到另一个页面 在 JavaScript 函数中 我正在检查条件 如果不满足这个条件 我想中止导航 以便OnClick方法未被调用
  • 主题以编程方式设置。如何重新加载 Activity 来应用

    如何在不重新启动整个应用程序的情况下应用主题 如果我这样做startActivity getIntent finish 活动退出并且不重新启动 是否可以简单地重新启动 重新创建活动来应用主题 它的顺序不正确 finish intent ne
  • JavaFX 中的 fx:id 和 id: 有什么区别?

    也许是一个真正的新手的问题 我开始通过阅读以下教程在 FMXL 应用程序中使用场景生成器学习 JavaFX http docs oracle com javase 8 javafx get started tutorial fxml tut
  • ASP.NET IIS 7.5 HTTP 500.21 错误

    我在设置本地站点时遇到问题 该项目使用 ASP NET Framework 4 0 我的 DefaultAppPool 使用 4 0 并集成托管管道模式 这是我得到的错误 HTTP Error 500 21 Internal Server
  • 如何使用表内的 JSONB 数据类型和 PostgreSQL JDBC 驱动程序将 JSON 对象存储到 PostgreSQL 中

    我想将以下 json 对象保存到 PostgreSQL 数据库表中as jsonb fname john lname doe 我当前使用 PGObject 创建对象并将类型设置为 jsonb 并将值作为 json 字符串传递 寻找更好的 m
  • 检查 XML 元素是否存在

    如何验证 XML 文件中是否存在特定元素 假设我有一个不断变化的 XML 文件 我需要在读取 解析它之前验证每个元素是否存在 if doc SelectSingleNode mynode null 应该这样做 显然 其中 doc 是您的 X
  • JSON 中的哈希到底是什么?

    我正在学习 JSON 但我发现你也可以将所谓的 哈希 放入 JSON 中 我在哪里可以找到什么是哈希 或者你能向我解释一下什么是哈希吗 另外 什么是哈希图 我有 C 和 C 经验 正在学习 JS Jquery 和 JSON 哈希是一个稀疏数
  • 我的 MS Access 数据库不会更新 asp.net

    我正在尝试更新我的数据库但没有成功 这就是我的桌子的样子 https i stack imgur com Q6EDk png https i stack imgur com Q6EDk png 打开模态后 它看起来像这样 https i s
  • MSMQ接收和删除

    是否有任何选项可以在读取消息后将其从 MSMQ 中删除 比如 接收 删除可以作为原子操作运行吗 听起来您想查看下一条消息 然后在处理完成后接收它 Message message Queue Peek Queue ReceiveById me
  • 无法加载 SQL Server Compact 的本机组件

    我已经在 Win7 x64 上安装了 SQL Server Compact Edition 4 0 它可以运行于 Asp Net 和桌面应用程序 此 PC 还安装了 Visual Studio 2010 SP1 但是我的 Server 20
  • 如何在新窗口中打开图像或pdf文件?

    我有一个 gridview 它包含文件名和文件路径 图像和 pdf 格式文件 其中我使用了模板字段 在该字段下放置了 1 个图像按钮 单击该图像按钮 即 查看 按钮 时 我想在新窗口中打开所选文件 这是我的代码 protected void

随机推荐