Newtonsoft反序列化将空值添加到列表中

时间:2016-01-15 01:52:02

标签: c# json serialization json.net

我只是尝试使用C#中的Newtonsoft JSON库将一些JSON从文件反序列化为对象列表。以下是 MeetingFile.txt 文件的内容:

[
  {
    "People": [
      {
        "FirstName": "Malcolm",
        "LastName": "Reynolds"
      },
      {
        "FirstName": "Hoban",
        "LastName": "Washburne"
      }
    ],
    "PairDate": "1/14/2016"
  }
]

以下是反序列化对象图的代码:

using (var streamReader = new StreamReader(@"C:\Temp\MeetingFile.txt"))
{
    var fileContents = streamReader.ReadToEnd();
    var meetingHistory = JsonConvert.DeserializeObject<List<PairHistoryItem>>(fileContents);
    var serialized = JsonConvert.SerializeObject(meetingHistory);
    return meetingHistory;
}

班级:

public class Person
{
    public readonly string FirstName;
    public readonly string LastName;
    public string FullName => $"{FirstName} {LastName}";

    public List<IPairHistoryItem> PairHistory;

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}

public class PairHistoryItem
{
    public List<Person> People { get; }
    public DateTime PairDate { get; }

    public PairHistoryItem(Person person1, Person person2, DateTime pairDate)
    {
        People = new List<Person> {person1, person2};
        PairDate = pairDate;
    }
}

但无论出于何种原因,这都是我的反序列化代码中 序列化 变量中包含的内容:

[
  {
    "People": [
      null,
      null,
      {
        "FirstName": "Malcolm",
        "LastName": "Reynolds",
        "PairHistory": null,
        "FullName": "Malcolm Reynolds"
      },
      {
        "FirstName": "Hoban",
        "LastName": "Washburne",
        "PairHistory": null,
        "FullName": "Hoban Washburne"
      }
    ],
    "PairDate": "2016-01-14T00:00:00"
  }
]

列表开头的空值来自哪里?据我所知,我文件中的JSON格式正确。我错过了JSON转换器的一些设置吗?

4 个答案:

答案 0 :(得分:4)

@Nikolai Samteladze完美地总结了这个问题的原因。除了更改构造函数之外,另一个可能的解决方案是将Json.Net配置为在反序列化期间替换现有列表而不是重用它。为此,您可以将ObjectCreationHandling设置为Replace(默认为Auto):

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ObjectCreationHandling = ObjectCreationHandling.Replace;

var meetingHistory = JsonConvert.DeserializeObject<List<PairHistoryItem>>(fileContents, settings);

但是,为了使其正常工作,您还需要为People类中的PairHistoryItem属性添加私有设置器,并使用[JsonProperty]属性对其进行标记,以便Json.Net可以“看到”它:

public class PairHistoryItem
{
    [JsonProperty]
    public List<Person> People { get; private set; }
    public DateTime PairDate { get; }

    public PairHistoryItem(Person person1, Person person2, DateTime pairDate)
    {
        People = new List<Person> {person1, person2};
        PairDate = pairDate;
    }
}

小提琴:https://dotnetfiddle.net/Zs5GI1

答案 1 :(得分:3)

问题是由PairHistoryItem类中构造函数的定义方式引起的。具体来说,您的ONLY构造函数使用2个对象填充People列表。

据我所知,JsonConvert.Deserialize首先在用数据填充之前创建一个对象。因此,首先,JsonConvert.Deserialize通过调用构造函数并提供PairHistoryItem作为参数来创建null实例。然后它添加了反序列化的2个Person个实例。因此,您最终会在People列表中找到4个元素:2 x null和2 x Person

最简单的解决方案是只为您的PairHistoryItem类添加默认构造函数。

public PairHistoryItem
{
    People = new List<Person>();
}

答案 2 :(得分:0)

您必须指定NullValueHandling的值才能忽略。

JsonSerializer serializer = new JsonSerializer { NullValueHandling = NullValueHandling.Ignore  };

请注意,如果您使用自定义序列化程序,则必须明确处理此问题。

答案 3 :(得分:0)

我遇到了类似的问题-所有项目都包含null。 然后我注意到忘了添加属性!像[JsonProperty]等。也许您像我一样专心,它将为您提供帮助!