【问题标题】:Newtonsoft deserialization adds nulls to listNewtonsoft 反序列化将空值添加到列表中
【发布时间】:2020-06-24 22:19:38
【问题描述】:

我只是尝试使用 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;
    }
}

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

[
  {
    "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 转换器的一些设置?

【问题讨论】:

  • 那些 RO 字段无法设置,在 Debug 中钻入meetingHistory 并且名称已经为空:i.stack.imgur.com/Gud9U.jpg 自然,当您重新序列化它时,它仍然是空的。 json 也没有与 person 类中的 PairHistory 相关的任何内容。
  • 嗯,奇怪的是我有两个空对象以及正确填充的对象,如上所述。所以它并不是真正的只读属性,而是构造函数。 @Nikolai Samteladze 似乎在正确的轨道上。

标签: c# json serialization json.net


【解决方案1】:

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

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

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

但是,为了使其正常工作,您还需要在 PairHistoryItem 类中为 People 属性添加私有设置器,并使用 [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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 这绝对是问题所在。解决方案基本上就是您所建议的: public PairHistoryItem(List people, DateTime pairDate) { People = people;配对日期 = 配对日期;我不能有一个默认构造函数,而没有属性具有关联的反序列化器集来填充属性。现在,我有点希望它们只是 get 并将对象视为不可变的。
    【解决方案3】:

    您必须将NullValueHandling 的值指定为忽略。

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

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

    【讨论】:

    • 我认为这有助于将PairHistory 属性设置为null,但不会在People 列表中删除这些额外的null
    【解决方案4】:

    我遇到了这样的问题 - 所有项目都包含空值。 然后我注意到忘记添加属性了!像 [JsonProperty] 等等。可能你和我一样不专心,它会帮助你!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-28
      • 1970-01-01
      • 2013-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多