c# - 将 Newtonsoft.Json 与嵌套自定义类一起使用

标签 c# json serialization json.net

我需要序列化一些自定义对象以存储信息。但是,我正在努力将这些对象从序列化的 JSON 字符串反序列化回其原始对象形式。

序列化的字符串看起来不错:

[
  {
    "MyStringArray": [
      "stringInput1",
      "stringInput2"
    ],
    "MyCharArray": [
      "a",
      "b",
      "c",
      "."
    ],
    "MyString": "dummy",
    "MyClass3Object": [
      {
        "MyString": "ListInput1"
      },
      {
        "MyString": "ListInput2"
      }
    ]
  }
]

但是,当我重建原始 MyClass1 对象时,列表应有一个条目,但它填充了空值而不是相应的数据。关于可能发生的事情有什么想法吗?预先感谢您的集思广益:)

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.IO;
using System.Text.RegularExpressions;

namespace JsonTesting
{
  class Program
  {
    static void Main(string[] args)
    {

      MyClass1 c1 = new MyClass1();
      c1.AddInfo();

      string toJsonString = JsonConvert.SerializeObject(c1, Formatting.Indented,
        new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Include });
      File.WriteAllText(@"C:\temp\dumpJsonText.txt",toJsonString);
      MyClass1 fromJson = JsonConvert.DeserializeObject<MyClass1>(toJsonString);
      Console.ReadLine();

    }
  }


  public class MyClass1 : List<MyClass2> {
    public MyClass1() { }
    public void AddInfo() {
      this.Add(new MyClass2(new string[] { "stringInput1", "stringInput2" },
        new char[] { 'a', 'b', 'c', '.' },
        "dummy",
        new List<MyClass3>() { new MyClass3("ListInput1", new Regex(@"[A-Z]")), new MyClass3("ListInput2", new Regex(@"[0-9]")) }
        ));
    }
  }

  public class MyClass2
  {
    private string[] _myStringArray = null;
    private char[] _myCharArray = null;
    private string _myString = null;
    private List<MyClass3> _myClass3Object = null;

    public MyClass2() { }

    public MyClass2(string[] myStringArray, char[] myCharArray, string myString, List<MyClass3> myClass3Object)
    {
      _myStringArray = myStringArray;
      _myCharArray = myCharArray;
      _myString = myString;
      _myClass3Object = myClass3Object;
    }

    public string[] MyStringArray { get { return _myStringArray; } }
    public char[] MyCharArray { get { return _myCharArray; } }
    public string MyString { get { return _myString; } }
    public List<MyClass3> MyClass3Object { get { return _myClass3Object; } }

  }

  public class MyClass3 {

    private Regex _myRegex; 
    private string _myString = null;
    public MyClass3() { }
    public MyClass3(string myString, Regex myRegex) {

      _myString = myString;
      _myRegex = myRegex;
    }

    public string MyString{ get {return _myString;} }

  }

}

最佳答案

您的类 MyClass2MyClass3 是只读的。为了让 Json.NET 反序列化只读类型,您必须提供 custom JsonConverter手动反序列化并构造类型的实例,或提供参数化构造函数,其参数名称与属性名称模大小写匹配。您已经创建了必要的构造函数,因此已经完成了一半。

但是您的类型也有无参数构造函数。那么,Json.NET 调用哪个构造函数呢?对于序列化为 JSON object 的非枚举类型,以下规则适用:

  1. 如果[JsonConstructor]在构造函数上设置,请使用该构造函数。

  2. 下一步,在 full trust only ,当应用 MemberSerialization.Fields 或应用 [Serialized]DefaultContractResolver.IgnoreSerializableAttribute == false 时,特殊方法FormatterServices.GetUninitializedObject()用于分配对象。 没有调用任何类型的构造函数。

    (这是一个不常见的情况,并不经常出现。)

  3. 接下来,如果有公共(public)无参数构造函数,请使用它。

  4. 接下来,如果存在私有(private)无参数构造函数并且设置 ConstructorHandling.AllowNonPublicDefaultConstructor 启用时,使用私有(private)无参数构造函数。

  5. 接下来,如果有单个公共(public)参数化构造函数,请使用该构造函数。

  6. 如果不满足上述所有条件,Json.NET 就无法构造该类型的实例。除非有自定义转换器可用,否则反序列化期间将引发异常。

因此,无参数构造函数优先于有参构造函数。要强制使用参数化构造函数,请使用上面提到的 [JsonConstructor] 标记它们:

public class MyClass3
{
    private Regex _myRegex;
    private string _myString = null;

    public MyClass3() { }

    [JsonConstructor]
    // The argument names must match the property names modulo case for Json.NET to deserialize the properties successfully.
    public MyClass3(string myString, Regex myRegex)
    {
        _myString = myString;
        _myRegex = myRegex;
    }

    public string MyString { get { return _myString; } }

    public Regex MyRegex { get { return _myRegex; } }
}

或者,您可以消除无参数构造函数,因为它显然在问题的第一个版本中不存在。然后对 MyClass2 进行相同的更改。现在您的类型将成功反序列化。

请注意,Json.NET 有一个 built-in converter用于序列化 Regex

样本fiddle .

关于c# - 将 Newtonsoft.Json 与嵌套自定义类一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41551530/

相关文章:

c# - 如何在 C# 中将 DateTimeOffset 添加到 DateTime?

android - Volley 认证 header

java - 如何通过 Jackson 生成器对值进行 html 转义

c# - 在桌面上序列化,在 Silverlight 中反序列化

c# - 将新行附加到文件的最简洁/最短的方法

c# - 批量分组数组

c# - 使用文本 JSON 属性序列化匿名类型

javascript - 成功通过EJS向客户端传递了一个数据数组,但是在我添加索引值的时候不让我在客户端访问数组

c# - 如何智能解析xml?(使用状态机?)

java - 如何在不实现 Serializable 接口(interface)的情况下序列化/反序列化对象?