【问题标题】:Json.Net JsonConvert.SerializeObject json not correctJson.Net JsonConvert.SerializeObject json 不正确
【发布时间】:2014-11-25 09:23:26
【问题描述】:

我使用Json.net的最新版本(6.0.6)序列化一个对象,在我看来,结果是不正确的。

下面c#示例的结果是这样的:

"Key":"AAA","No":"BBB","Project_No":"CCC","Resource_No":"DDD","Resource_Group_No":"EEE","Stadium_Code":"FFF","Entry_NoSpecified":false,"Line_NoSpecified":false,"Execution_DateSpecified":false,"HoursSpecified":false,"ExecutedSpecified":false,"FixedSpecified":false,"ConfirmedSpecified":false,"Begin_TimeSpecified":false,"Updated_TimeSpecified":false

如您所见,所有非字符串属性都没有序列化,例如 Entry_No、Line_No、Hours 和 dates

这是 Json.Net 中的错误吗?

重现问题的代码,

using System;
using Newtonsoft.Json;

namespace JSONNET
{
    class Program
    {
        static void Main(string[] args)
        {
            var dto = new ProjectPlanningEntryDto()
            {
                Key = "AAA",
                No = "BBB",
                Entry_No = 123,
                Project_No = "CCC",
                Line_No = 456,
                Resource_No = "DDD",
                Resource_Group_No = "EEE",
                Execution_Date = DateTime.Now,
                Hours = 4,
                Begin_Time = DateTime.Now,
                Updated_Time = DateTime.Now,
                Stadium_Code = "FFF"
            };

            var json = JsonConvert.SerializeObject(dto);

            Console.WriteLine(json);
            Console.ReadLine();
        }
    }

    public class ProjectPlanningEntryDto
    {
        public string Key { get; set; }
        public string No { get; set; }
        public int Entry_No { get; set; }
        public string Project_No { get; set; }
        public int Line_No { get; set; }
        public string Resource_No { get; set; }
        public string Resource_Group_No { get; set; }
        public DateTime Execution_Date { get; set; }
        public decimal Hours { get; set; }
        public bool Executed { get; set; }
        public bool Fixed { get; set; }
        public bool Confirmed { get; set; }
        public DateTime Begin_Time { get; set; }
        public DateTime Updated_Time { get; set; }
        public string Stadium_Code { get; set; }
        public bool Entry_NoSpecified { get; set; }
        public bool Line_NoSpecified { get; set; }
        public bool Execution_DateSpecified { get; set; }
        public bool HoursSpecified { get; set; }
        public bool ExecutedSpecified { get; set; }
        public bool FixedSpecified { get; set; }
        public bool ConfirmedSpecified { get; set; }
        public bool Begin_TimeSpecified { get; set; }
        public bool Updated_TimeSpecified { get; set; }
    }
}

【问题讨论】:

  • 如果您将(例如)Entry_NoSpecified 设置为 true 会发生什么?
  • 嗯,如果我将 Entry_NoSpecified 设置为 true,则 Entry_No 字段将被序列化。这意味着指定的属性会调用我不知道的特殊行为?
  • 在版本 4(2011 年 1 月)中,他们添加了 XmlSerializer 样式指定的属性支持。发现它潜伏在这些发行说明中并不显眼:james.newtonking.com/archive/2011/01/03/…

标签: c# json json.net


【解决方案1】:

根据version 4 release blog post,Json.NET 似乎遵守使用<Name>Specified 属性来查看它是否应该序列化属性的约定。所以,

var dto = new ProjectPlanningEntryDto()
{
    Key = "AAA",
    No = "BBB",
    Entry_No = 123,
    Entry_NoSpecified = true,
    Project_No = "CCC",
    Line_No = 456,
    Line_NoSpecified = true,
    ...
};

会产生你想要的 json 对象。此约定的应用方式与应用于 XmlSerializer 的方式相同,详见此处:MSDN: System.Xml.Serialization.XmlSerializer

另一种选择是使用特殊模式来创建 XmlSerializer 识别的布尔字段,并将 XmlIgnoreAttribute 应用于该字段。该模式以 propertyNameSpecified 的形式创建。例如,如果有一个名为“MyFirstName”的字段,您还将创建一个名为“MyFirstNameSpecified”的字段,它指示 XmlSerializer 是否生成名为“MyFirstName”的 XML 元素。这在以下示例中显示。

public class OptionalOrder
{
    // This field should not be serialized 
    // if it is uninitialized.
    public string FirstOrder;

    // Use the XmlIgnoreAttribute to ignore the 
    // special field named "FirstOrderSpecified".
    [System.Xml.Serialization.XmlIgnoreAttribute]
    public bool FirstOrderSpecified;
}

要应用相同的逻辑 - 而不是序列化 json 中的 <Name>Specified 属性 - 只需使用 JsonIgnoreAttribute 来装饰这些属性。

【讨论】:

  • 您能简单解释一下什么是指定属性吗?我没有运气用谷歌搜索它:(
  • @t3chb0t 添加了更多信息。希望这能说明问题。谷歌搜索“指定”有点困难,我知道,因为我做了很多甚至在 Json.NET 上找到信息。 ;)
【解决方案2】:

这一定是 JSON.NET 中的错误,因为当我从 DateTime 属性中删除下划线时,它们被正确序列化了。

【讨论】:

  • ...是的,因为您没有匹配的指定属性。所以不行。不是错误。
猜你喜欢
  • 2014-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多