考虑以下模型
public class Root
{
public static int latestID = 0;
public Root()
{
SpecificBranchA = new A(this) { BranchID = latestID + 1 };
}
public A SpecificBranchA { get; }
}
public class A
{
public Root Owner { get; }
public int BranchID { get; set; }
[JsonConstructor]
public A(Root owner)
{
Owner = owner;
}
public List<B> Children { get; } = new List<B>();
}
public class B
{
public A Owner { get; }
public int LeafID { get; set; }
[JsonConstructor]
public B(A owner)
{
Owner = owner;
}
}
和此示例实例:
var root = new Root();
root.Obj.Children.Add(new B(root.Obj) { LeafID = 1 });
root.Obj.Children.Add(new B(root.Obj) { LeafID = 2 });
root.Obj.Children.Add(new B(root.Obj) { LeafID = 3 });
当使用这些设置进行序列化时,这会给出错误的json:
var res = JsonConvert.SerializeObject(root, new JsonSerializerSettings()
{
PreserveReferencesHandling = PreserveReferencesHandling.All,
ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
TypeNameHandling = TypeNameHandling.Objects, //only for reading simplicity
Formatting = Formatting.Indented //only for reading simplicity
});
结果:
{
"$id": "1",
"$type": "TestJSONSerializer.Root, TestJSONSerializer",
"SpecificBranchA": {
"$type": "TestJSONSerializer.A, TestJSONSerializer",
"Owner": {
"$ref": "1"
},
"BranchID": 1,
"Children": [
{
"$id": "2",
"$type": "TestJSONSerializer.B, TestJSONSerializer",
"Owner": {
"$id": "3",
"$type": "TestJSONSerializer.A, TestJSONSerializer",
"Owner": {
"$ref": "1"
},
"BranchID": 1,
"Children": [
{
"$ref": "2"
},
{
"$id": "4",
"$type": "TestJSONSerializer.B, TestJSONSerializer",
"Owner": {
"$ref": "3"
},
"LeafID": 2
},
{
"$id": "5",
"$type": "TestJSONSerializer.B, TestJSONSerializer",
"Owner": {
"$ref": "3"
},
"LeafID": 3
}
]
},
"LeafID": 1
},
{
"$ref": "4"
},
{
"$ref": "5"
}
]
}
}
在这里您可以注意到,在A
的构造函数中存储在属性A.SpecificBranchA
中的对象创建了两次序列化,并且出现了一些奇怪的嵌套行为。
但是当单独序列化A
对象时,您不会得到这种行为。
(是的,当您致电JsonConvert.SerializeObject(root.SpecificBranchA,...)
时不会发生这种情况)
它看起来像是Json.net中的错误,但我不确定自己做错了什么
答案 0 :(得分:1)
所以看来我不是按照Json.net的设计以错误的方式做事(感谢@dbc的评论)
我稍微改变了模型,一切正常
在根类中,我将属性SpecificBranchA
的定义更改为以下内容
[JsonProperty]
public A SpecificBranchA { get; private set; }
,序列化将按预期进行。
因此,我认为任何包含带有引用循环的对象的属性,都必须具有一个setter(即使是私有的)并标有[JsonProperty]
。如果缺少任何一个,则序列化会得到错误的行为。
相关问题