Json.net反序列化列表提供重复项

我刚开始使用Newtonsoft.Json(Json.net)。 在我的第一个简单测试中,我在反序列化通用列表时遇到了问题。 在下面的代码示例中,我序列化了一个对象,包含三种类型的简单整数列表(属性,成员var和数组)。

生成的json看起来很好(列表转换为json数组)。 但是,当我将json反序列化为相同类型的新对象时,所有列表项都是重复的,期望数组。 我已经通过第二次序列化来说明了这一点。

从搜索周围,我已经读到可能有一个“私人”支持字段到解串器也填充的列表。

所以我的问题是:在下列情况下是否有一种(最好是简单的)避免重复项目的方法?

using System; using System.Collections.Generic; using Newtonsoft.Json; namespace JsonSerializeExample { public class Program { static void Main() { var data = new SomeData(); var json = JsonConvert.SerializeObject(data); Console.WriteLine("First : {0}", json); var data2 = JsonConvert.DeserializeObject(json); var json2 = JsonConvert.SerializeObject(data2); Console.WriteLine("Second: {0}", json2); } } public class SomeData { public string SimpleField; public int[] IntArray; public IList IntListProperty { get; set; } public IList IntListMember; public SomeData() { SimpleField = "Some data"; IntArray = new[] { 7, 8, 9 }; IntListProperty = new List { 1, 2, 3 }; IntListMember = new List { 4, 5, 6 }; } } } 

产生的结果

 First : {"SimpleField":"Some data","IntArray":[7,8,9],"IntListMember":[4,5,6],"IntListProperty":[1,2,3]} Second: {"SimpleField":"Some data","IntArray":[7,8,9],"IntListMember":[4,5,6,4,5,6],"IntListProperty":[1,2,3,1,2,3]} 

这里可能存在一些重叠, Json.Net复制了私有列表项 。 但是,我认为我的问题更简单,我仍然没有想到它。

那是因为您要在构造函数中添加项目。 处理列表时反序列化器中的常用方法基本上是:

  • 通过getter读取列表
    • 如果列表为null:创建一个新列表并通过属性setter分配(如果有)
  • 依次反序列化每个项目,并将( Add )附加到列表中

这是因为大多数列表成员没有setter ,即

 public List Items {get {...}} // <=== no set 

与数组形成对比,数组必须有一个有用的setter; 因此,方法通常是:

  • 依次反序列化每个项目,并将( Add )附加到临时列表
  • 将列表转换为数组( ToArray ),并通过setter进行分配

一些序列化程序为您提供了控制此行为的选项(其他人没有); 并且一些序列化程序使您能够完全绕过构造函数(其他人没有)。

我遇到了一个不同根本原因的类似问题。 我正在序列化和反序列化一个看起来像这样的类:

 public class Appointment { public List Revisions { get; set; } public AppointmentRevision CurrentRevision { get { return Revision.LastOrDefault(); } } public Appointment() { Revisions = new List(); } } public class AppointmentRevision { public List Attendees { get; set; } } 

当我序列化时,CurrentRevision也被序列化了。 我不确定如何,但是当它反序列化时,它正确地保留了AppointmentRevision的单个实例,但在Attendees列表中创建了重复项。 解决方案是在CurrentRevision属性上使用JsonIgnore属性。

 public class Appointment { public List Revisions { get; set; } [JsonIgnore] public AppointmentRevision CurrentRevision { get { return Revision.LastOrDefault(); } } public Appointment() { Revisions = new List(); } }