Newtonsoft json反序列化将缺少的int值设置为null而不是零

时间:2018-09-04 15:19:50

标签: c# json.net

是否可以通过这种方式调整JsonSerializerSettings?

(我想不是),但仍然有一些希望,因为我对他们的API不太了解。

默认情况下,在所有设置下,我都尝试将int反序列化为0或导致异常。

示例

   {
      "defaultCaptionLineNum": 6,
      "worksheets": {
        "0": { "name": "Ws1", "caption_ln": 6 },
        "1": { "name": "Ws2", "caption_ln": null },
        "2": { "name": "Ws3" },
        "3": { "name": "Ws4", "caption_ln": 5 },
      }
}

当前默认情况下,Ws3的标题行(caption_ln)评估为0,我希望将其评估为null(与Ws2一样)。

我正在使用

jObject.ToObject<MyClass>(JsonSerializer.Create(settings));

从JSON获取带有工作表(Ws)信息的对象(也尝试了不使用序列化器的情况)

以及此处的IncludeIgnore的任何变体都不会使jObject对json中丢失的int进行反序列化(除非立即对丢失的值抛出错误)

var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Include,
MissingMemberHandling = MissingMemberHandling.Ignore
};

其他序列化程序设置似乎无关。

UPD: MyObject MyClass的列表。

public class MyClass
{
    public class WorkSheet
    {
        [JsonProperty("name")]
        string wsName;

        [JsonProperty("caption_ln")]
        int? captionLineNumber;

        public WorkSheet(string name, int captionln)
        {
            wsName = name;
            captionLineNumber = captionln;
        }
    }
    private int _defaultCaptionLineNum;

    [JsonProperty("defaultCaptionLineNum")]
    public int DefaultCaptionLineNum { get => _defaultCaptionLineNum; }

    private Dictionary<int, WorkSheet> _worksheets = new Dictionary<int, WorkSheet>();

    [JsonProperty("worksheets")]
    public Dictionary<int, WorkSheet> Worksheets { get => _worksheets; set => _worksheets = value; }

    public MyClass()
    {           
        Console.WriteLine("New MyClass object created!");
    }
}

1 个答案:

答案 0 :(得分:5)

您的问题是您的类型WorkSheet仅具有一个参数化的构造函数:

public class WorkSheet
{
    public WorkSheet(string name, int captionln)
    {
        wsName = name;
        captionLineNumber = captionln;
    }

    // Remainder omitted
}

如文档页面ConstructorHandling Enumeration中所述,当没有无参数构造函数时,Json.NET将退回到单个参数化构造函数,在这种情况下就是这样。对于构造函数参数,Json.NET将按名称(取模)将JSON参数与构造函数参数匹配,如果存在,则反序列化为参数类型,如果不存在,则传递默认值。而且,由于JSON中没有"captionln"参数,因此captionLineNumber被初始化为default(int)0。这说明了您遇到的问题。

要解决此问题,您可以将captionln更改为int?类型:

public class WorkSheet
{
    public WorkSheet(string name, int? captionln)
    {
        wsName = name;
        captionLineNumber = captionln;
    }

    // Remainder omitted
}

工作中的小提琴#1 here

或者,您可以引入专用于序列化的私有构造函数,并用[JsonConstructor]进行标记:

public class WorkSheet
{
    [JsonConstructor]
    private WorkSheet() { }

    public WorkSheet(string name, int captionln)
    {
        wsName = name;
        captionLineNumber = captionln;
    }

    // Remainder omitted
}

样本小提琴#2 here

有关在Json.NET中使用构造函数的相关问题: