项目场景:
Newtonsoft循环引用与自引用反序列化null值问题
问题描述
正确设置了PreserveReferencesHandling.Objects
与ReferenceLoopHandling.Serialize
序列化成功,json文件中确实被记录,反序列化后JsonConvert.DeserializeObject反序列化完成
得到空值
原因分析:
空值为引用项,在json文件中发生自引用或循环引用,即A引用了A自身或A引用了B,而B又引用了A,即便设置了PreserveReferencesHandling.Objects
与ReferenceLoopHandling
也只能达到A引用B,C引用B的情况下被正确设置,无法避免反序列化之后自引用为null值或循环引用B对A的引用为null
值
解决方案:
使用默认构造函数进行反序列化
对于自引用与循环引用的详细分析
在官方文档PreserveReferencesHandling
下的Note
已经写明
当通过非默认构造函数设置值时,无法保留引用。对于非默认构造函数,子值必须在父值之前创建,以便它们可以传递到构造函数中,从而无法跟踪引用。 ISerialized 类型是一个类的示例,其值使用非默认构造函数填充,并且不能与 PreserveReferencesHandling 一起使用。
所以推测反序列化一个类时,如果使用默认无参
构造函数则继续反序列化,而如果使用非默认有参
构造函数,则会停止这个类的反序列化,优先序列化这个类父值
下面的成员子值
,以便将子值作为参数传入构造函数在参数与子值成员名相同的情况下,会使用构造函数反序列化,名称无视大小写
,这就导致子值在反序列化时,他们对于父值的引用为null,因为此时父值还未创建,而json文件中又是使用ref
对父值的id
进行引用,而不会在此反序列化父值