在使用反序列化对象时,将一些父实例传递给构造函数时遇到一个小问题Newtonsoft.Json
.
我们假设我有以下课程
public class A { public string Str1 { get; set; } public IList Bs { get; set; } } public class B { public B(A a) { // a should not be null! Console.WriteLine(a.Str) } }
现在我a
像这样serailze而不是反序列化对象:
A a = new A() a.Bs = new List() a.Bs.Add(new B(a)); a.Bs.Add(new B(a)); a.Bs.Add(new B(a)); var json = JsonConvert.SerializeObject(a); // Here i need to call the constructor of B when creating new instances var newA = JsonConvert.DeserializeObject(json);
问题是,在反序列化对象时,null
会将其传递给构造函数B
.有没有人以前解决过这个问题?
非常感谢你!
在您的问题和评论中,您已经说过该课程B
没有任何公共财产A
.因此,当您序列化时B
,则不A
会将任何内容写入JSON,因为Json.Net默认只序列化公共信息.因此,在反序列化时,将没有足够的信息来重新创建B
,因为A
JSON中没有.所以,第一步是B
引用A
Json.Net可见.如果您不想将其公开,那很好,但您至少需要使用[JsonProperty]
属性标记该成员以允许Json.Net"看到"它.
public class B { [JsonProperty] private A a; public B(A a) { this.a = a; // be sure to set the A member in your constructor } }
现在,如果你执行上述操作,你将遇到第二个问题:你的类结构有一个引用循环(A
有一个B
s 列表,每个引用回来A
),在这种情况下,序列化器默认会抛出异常.解决方案是将序列化程序的PreserveReferencesHandling
设置设置为Objects
(默认值为None
).这不仅允许序列化程序在序列化期间处理引用循环,而且还将在反序列化期间保留原始引用,以便所有B
s将引用相同的A
实例.(这是通过写入JSON的特殊$id
和$ref
属性来完成的.)
JsonSerializerSettings settings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects, }; var json = JsonConvert.SerializeObject(a, settings); var newA = JsonConvert.DeserializeObject(json, settings);
工作示例:https://dotnetfiddle.net/N0FUID