我需要序列化一些自定义对象以存储信息。但是,我正在努力将这些对象从序列化的 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;} }
}
}
最佳答案
您的类 MyClass2
和 MyClass3
是只读的。为了让 Json.NET 反序列化只读类型,您必须提供 custom JsonConverter
手动反序列化并构造类型的实例,或提供参数化构造函数,其参数名称与属性名称模大小写匹配。您已经创建了必要的构造函数,因此已经完成了一半。
但是您的类型也有无参数构造函数。那么,Json.NET 调用哪个构造函数呢?对于序列化为 JSON object 的非枚举类型,以下规则适用:
如果
[JsonConstructor]
在构造函数上设置,请使用该构造函数。下一步,在 full trust only ,当应用
MemberSerialization.Fields
或应用[Serialized]
且DefaultContractResolver.IgnoreSerializableAttribute == false
时,特殊方法FormatterServices.GetUninitializedObject()
用于分配对象。 没有调用任何类型的构造函数。(这是一个不常见的情况,并不经常出现。)
接下来,如果有公共(public)无参数构造函数,请使用它。
接下来,如果存在私有(private)无参数构造函数并且设置
ConstructorHandling.AllowNonPublicDefaultConstructor
启用时,使用私有(private)无参数构造函数。接下来,如果有单个公共(public)参数化构造函数,请使用该构造函数。
如果不满足上述所有条件,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/