Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json.net 反序列化自引用属性不起作用_Json.net - Fatal编程技术网

Json.net 反序列化自引用属性不起作用

Json.net 反序列化自引用属性不起作用,json.net,Json.net,我有一个具有父属性的对象,它引用了另一个相同类型的对象: [JsonObject(IsReference = true)] class Group { public string Name { get; set; } public Group(string name) { Name = name; Children = new List<Group>(); } public IList<Group>

我有一个具有父属性的对象,它引用了另一个相同类型的对象:

[JsonObject(IsReference = true)]
class Group
{
    public string Name { get; set; }

    public Group(string name)
    {
        Name = name;
        Children = new List<Group>();
    }

    public IList<Group> Children { get; set; }

    public Group Parent { get; set; }

    public void AddChild(Group child)
    {
        child.Parent = this;
        Children.Add(child);
    }
}
但反序列化不起作用。父属性返回空值

测试如下所示:

{
  "$id": "1",
  "Name": "Parent",
  "Children": [
    {
      "$id": "2",
      "Name": "Child",
      "Children": [],
      "Parent": {
        "$ref": "1"
      }
    }
  ],
  "Parent": null
}
[Test]
public void Test()
{
    var child = new Group("Child");
    var parent = new Group("Parent");
    parent.AddChild(child);

    var json = JsonConvert.SerializeObject(parent, Formatting.Indented);
    Debug.WriteLine(json);

    var deserializedParent = (Group) JsonConvert.DeserializeObject(json, typeof(Group));
    Assert.IsNotNull(deserializedParent.Children.First().Parent);
}

我做错了什么?感谢您的帮助

使用引用不适用于只有带参数的构造函数的对象

Json.NET必须在创建父级之前反序列化所有子级值,它需要将这些值传递给构造函数,因此没有有效的父级引用可分配给子级。

要进一步展开,您可以通过为Json.NET提供无参数(默认)构造函数来解决此问题。如果您愿意,它可以是私有的,只要您还使用
[jsonstructor]
属性标记它

[JsonObject(IsReference = true)]
class Group
{
    ...

    [JsonConstructor]
    private Group()
    {
    }

    public Group(string name)
    {
        Name = name;
        Children = new List<Group>();
    }

    ...
}
[JsonObject(IsReference=true)]
班级
{
...
[JsonConstructor]
私人组()
{
}
公共组(字符串名称)
{
名称=名称;
Children=新列表();
}
...
}
这种安排允许Json.Net创建对象,而无需事先提供所有信息;之后,它可以使用公共属性来填充内容


Fiddle:

另一种方式,我发现,非常顽固的做法是创建两阶段反序列化,
正如我在下面所描述的

通常,我创建两个IContractResolver,其中一个只用于反序列化构造函数的属性(如果它有参数)

在第二阶段,我使用常规ContractResolver填充对象