为了存储信息,我需要序列化一些自定义对象。然而,我正在努力将这些对象从序列化的JSON字符串反序列化回它们的原始对象形式。
序列化的字符串似乎很好:
[
{
"MyStringArray": [
"stringInput1",
"stringInput2"
],
"MyCharArray": [
"a",
"b",
"c",
"."
],
"MyString": "dummy",
"MyClass3Object": [
{
"MyString": "ListInput1"
},
{
"MyString": "ListInput2"
}
]
}
]
然而,当我重构原始的MyClass1对象时,列表中有一个条目,但它填充了null,而不是相应的数据。对可能发生的事情有什么想法吗?提前感谢头脑风暴:)
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:tempdumpJsonText.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;} }
}
}
您的类MyClass2
和MyClass3
是只读的。为了Json。NET要反序列化只读类型,必须提供手动反序列化和构造该类型实例的自定义JsonConverter
,或者提供参数化构造函数,其参数名称与属性名称modulo-case匹配。您已经创建了必要的构造函数,所以已经完成了一半。
但是,您的类型也有无参数构造函数。那么,哪个构造函数做Json。NET调用?对于序列化为JSON对象的不可枚举类型,适用以下规则:
-
如果在构造函数上设置了
[JsonConstructor]
,请使用该构造函数。 -
接下来,在仅完全信任中,当应用
MemberSerialization.Fields
,或应用[Serializable]
和DefaultContractResolver.IgnoreSerializableAttribute == false
时,将使用特殊方法FormatterServices.GetUninitializedObject()
来分配对象没有调用任何类型的构造函数(这是一种不常见的情况。)
-
接下来,如果有一个公共的无参数构造函数,请使用它
-
接下来,如果存在私有无参数构造函数,并且设置
ConstructorHandling.AllowNonPublicDefaultConstructor
如果启用,则使用专用无参数构造函数。 -
接下来,如果存在单个公共参数化构造函数,请使用该构造函数。
-
以上都失败了,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有一个用于序列化CCD_ 12的内置转换器。
样品小提琴。