C# 当readonly属性与对象引用一起使用时Json.NET失败?

C# 当readonly属性与对象引用一起使用时Json.NET失败?,c#,.net,json,serialization,json.net,C#,.net,Json,Serialization,Json.net,编辑2016-12-05: 这被认为是一个bug,并已修复: 原创帖子: 我刚开始使用Json.NET,但是遇到了一些奇怪的行为,看起来像是一个bug 如果反序列化程序遇到最初在只读属性(get;only)中定义的对象引用($ref):“2”),它将无法反序列化并返回null 阶级 序列化: Parent p = new Parent() { Child = new Child() }; JsonConvert.SerializeObject(p, new JsonSerializerSetti

编辑2016-12-05: 这被认为是一个bug,并已修复:

原创帖子:

我刚开始使用Json.NET,但是遇到了一些奇怪的行为,看起来像是一个bug

如果反序列化程序遇到最初在只读属性(get;only)中定义的对象引用($ref):“2”),它将无法反序列化并返回null

阶级

序列化:

Parent p = new Parent() { Child = new Child() };
JsonConvert.SerializeObject(p, new JsonSerializerSettings()
{ Formatting = Formatting.Indented,
  PreserveReferencesHandling = PreserveReferencesHandling.Objects });
序列化:

{
  "$id": "1",
  "ReadOnlyChild": {
    "$id": "2",
  },
  "Child": {
    "$ref": "2"
  }
}
反序列化(重新序列化以显示更改(&R):

这是预期的行为,一个bug,还是我遗漏了什么

请注意,有时需要[JsonProperty(Order=#)来强制序列化程序首先对ReadOnlyChild执行操作。无论如何,上述序列化的JSON块将无法正确反序列化,即使该类已被修改为先反序列化子类

EDIT:我关心的是子属性是否为null,而不是ReadOnlyChild是否被Json.NET以某种方式赋值


谢谢

您是否考虑过阻止Json.Net序列化该属性

public class Parent
{
    [JsonIgnore] 
    public Child ReadOnlyChild
    {
        get
        {
            return Child;
        }
    }

    public Child Child {get; set;}
}

我从不使用引用跟踪,但查看您的数据,它似乎正在为您的
ReadOnlyChild
创建一个“id”,您是普通的
属性正在引用该id,在反序列化时,因为它无法还原
ReadOnlyChild
,整个参考资料追踪业务都搞砸了。@KirkWoll:这也是我得出的结论。我理解无法将子对象分配给ReadOnlyChild(毕竟没有集合),但它会丢弃该对象,而不是等到再次引用子属性时才将其丢弃。这纯粹是我的推测,但我怀疑发生的事情是,json.net成功地反序列化了
ReadOnlyChild
的值,尝试将其放入该属性中——失败,因为它不可写——并最终留下一个引用(在其内部模型中),即id
“2”
的值现在包含在
ReadOnlyChild
中(自从赋值失败后,它就没有值了。)然后它会得到
的值,
“$ref”:“2”
,尝试将其解析为
ReadOnlyChild
,并将其值设置为
null
。@Shoebox感谢您回来更新您的问题。这是一个很好的解决方法,可能是我的最终解决方案。如果您不需要Json中的ReadOnly字段,那么这很好。如果您确实需要它,那么就不太好了,但是需要它在返回值时忽略该值。@Shoebox我认为这不仅仅是一种解决方法:d
ReadOnlyChild
在这种情况下是一个计算值,根本不需要序列化。问题已经解决。我编辑了OP以反映这一点。
{
  "$id": "1",
  "ReadOnlyChild": null,
  "Child": null
}
public class Parent
{
    [JsonIgnore] 
    public Child ReadOnlyChild
    {
        get
        {
            return Child;
        }
    }

    public Child Child {get; set;}
}