将Newtonsoft.Json与嵌套的自定义类一起使用 [英] Using Newtonsoft.Json with nested custom classes

查看:99
本文介绍了将Newtonsoft.Json与嵌套的自定义类一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要序列化一些自定义对象以存储信息.但是,我正在努力将序列化JSON字符串中的那些对象反序列化为它们的原始对象形式.

I need to serialize some custom objects in order to store information. However, I am struggling to deserialize those objects from the serialized JSON string back into their original object forms.

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

The serialized string seems fine:

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

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

However, when I reconstruct the original MyClass1 object, the list has one entry as it should but it is filled with nulls instead of the corresnponding data. Any ideas as to what may be happening? Thanks in advance for the brainstorming :)

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 可以手动反序列化并构造该类型的实例,或者提供一个参数化的构造函数,该构造函数的自变量名称与模数大小写的属性名称相匹配.您已经创建了必要的构造函数,因此已完成一半.

Your classes MyClass2 and MyClass3 are read-only. In order for Json.NET to deserialize a read-only type, you must either provide a custom JsonConverter that manually deserializes and constructs an instance of the type, or provide a parameterized constructor whose argument names match the property names modulo case. You have already created the necessary constructors and so are halfway done.

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

However your types have parameterless constructors as well. So, which constructor does Json.NET call? For a non-enumerable type that is serialized to a JSON object, the following rules apply:

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

  1. If [JsonConstructor] is set on a constructor, use that constructor.

下一步,在 完全信任仅 (当应用 MemberSerialization.Fields 或应用[Serializable] FormatterServices.GetUninitializedObject() 用于分配对象. 该类型的构造函数均未调用.

Next, in full trust only, when MemberSerialization.Fields is applied, or [Serializable] is applied and DefaultContractResolver.IgnoreSerializableAttribute == false, the special method FormatterServices.GetUninitializedObject() is used to allocate the object. None of the type's constructors are called.

(这是一种罕见的情况,很少发生.)

(This is an unusual case that does not arise often.)

接下来,如果有一个公共的无参数构造函数,请使用它.

Next, if there is a public parameterless constructor, use it.

接下来,如果存在私有的无参数构造函数并且设置 ConstructorHandling.AllowNonPublicDefaultConstructor 启用后,将使用私有的无参数构造函数.

Next, if a private parameterless constructor exists and the setting ConstructorHandling.AllowNonPublicDefaultConstructor is enabled, the private parameterless constructor is used.

接下来,如果有一个单个公共参数化构造函数,请使用该构造函数.

Next, if there is a single public parameterized constructor, use that constructor.

上述所有操作均失败,Json.NET无法构造该类型的实例.除非可以使用自定义转换器,否则在反序列化期间将引发异常.

Failing all of the above, Json.NET cannot construct instances of the type. An exception will get thrown during deserialization unless a custom converter is available.

因此,无参数的构造函数优先于带参数的构造函数.要强制使用参数化的构造函数,请按上述用[JsonConstructor]标记它们:

Thus the parameterless constructors take precedence over the parameterized constructors. To force the parameterized constructors to be used, mark them with [JsonConstructor] as mentioned above:

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进行相同的更改.现在,您的类型将成功反序列化.

Alternatively, you could eliminate the parameterless constructor as it apparently did not exist in the first version of your question. Then make the same change to MyClass2. Now your types will deserialize successfully.

请注意,Json.NET具有内置转换器用于序列化Regex.

Note that Json.NET has a built-in converter for serializing a Regex.

示例小提琴.

这篇关于将Newtonsoft.Json与嵌套的自定义类一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆