如何将参数传递给构造函数反序列化json
在使用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
,因为JSON中没有A
因此,第一步是将B
引用到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
的列表,每个都引用回A
),在这种情况下,序列化器默认会抛出exception。 解决方案是将序列化程序的PreserveReferencesHandling
设置设置为Objects
(默认值为None
)。 这不仅允许串行器在序列化期间处理引用循环,而且还将在反序列化期间保留原始引用,以便所有B
都将引用相同的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