我需要序列化一些自定义对象才能存储信息。但是,我正在努力将序列化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;} }
}
}
答案 0 :(得分:1)
您的课程MyClass2
和MyClass3
是只读的。为了让Json.NET反序列化只读类型,您必须提供一个custom JsonConverter
来手动反序列化并构造该类型的实例,或者提供一个参数化构造函数,其参数名称与属性名称匹配模数。您已经创建了必要的构造函数,因此已经完成了一半。
但是你的类型也有无参数构造函数。那么,Json.NET调用哪个构造函数?对于序列化为JSON object的非可枚举类型,以下规则适用:
如果在构造函数上设置了[JsonConstructor]
,请使用该构造函数。
接下来,在full trust only中,当应用 MemberSerialization.Fields
或应用[Serializable]
并DefaultContractResolver.IgnoreSerializableAttribute == false
时,特殊方法{ {3}}用于分配对象。 不会调用任何类型的构造函数。
(这是一种不常见的情况。)
接下来,如果有一个公共无参数构造函数,请使用它。
接下来,如果存在私有无参数构造函数并且设置FormatterServices.GetUninitializedObject()
启用后,将使用私有无参数构造函数。
接下来,如果有一个单个公共参数化构造函数,请使用该构造函数。
如果不能解决上述问题,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有一个ConstructorHandling.AllowNonPublicDefaultConstructor
用于序列化Regex
。