【问题标题】:nested json objects dont update / inherit using Json.NET嵌套的 json 对象不使用 Json.NET 更新/继承
【发布时间】:2015-03-25 23:57:34
【问题描述】:

使用折旧的 System.Json,我得到了我期望的结果(来自 Javascript): 孩子得到一个孙子,所有的父母都知道......

var Parents         = new JsonObject();
var Children        = new JsonObject();

var Parent          = JsonArray.Parse("[]");
Parents.Add("1", Parent);

var Child           = JsonArray.Parse("[]");
Children.Add("1", Child);

var DstParent       = (JsonArray)Parents["1"];
DstParent.Add(Children["1"]);


var DstChild    = (JsonArray)Children["1"];
JsonObject GrandChild   = (JsonObject)JsonArray.Parse("{}");
GrandChild.Add("Age", 15);
DstChild.Add(GrandChild);

var Result = Parents.ToString();

给我:"{"1":[[{"Age":15}]]}"

使用 Newtonsoft.Json 6.0.8,父母没有得到“提示”它的孩子有一个孙子。

var Parents         = new JObject();
var Children        = new JObject();

var Parent          = JArray.Parse("[]");
Parents.Add("1", Parent);

var Child           = JArray.Parse("[]");
Children.Add("1", Child);

var DstParent       = (JArray)Parents["1"];
DstParent.Add(Children["1"]);


var DstChild    = (JArray)Children["1"];
var GrandChild  = JObject.Parse("{}");
GrandChild.Add("Age", 15);
DstChild.Add(GrandChild);

给我:"{"1":[[]]}"

我做错了什么?

【问题讨论】:

    标签: c# json


    【解决方案1】:

    出现问题是因为所有JToken 对象都有一个Parent 属性,该属性记录了它们在JSON 对象层次结构中的位置——但您正试图将JArray Child 添加到两个不同的不相关父母。首先,将其添加到 Children 对象(实际上不在您正在创建的 JSON 对象树中):

            Children.Add("1", Child);
    

    接下来将其添加到DstParent 数组(在您正在创建的 JSON 对象树中):

            DstParent.Add(Children["1"]);
    

    那么,Json.NET 在这种情况下做了什么?它可以:

    1. 尝试创建多父对象时抛出异常,或者
    2. 从之前的父对象中删除对象并将其移动到新的父对象,或者
    3. 在其新父对象中创建对象的克隆。

    事实证明,它需要选项#3:它将Children["1"] 复制到DstParent。我不确定是否或在哪里记录了这一点,但从 source code 中的 JContainer 可以明显看出 - 查找调用 EnsureParentTokenInsertItem。因此,当您将孙子添加到 DstChild 时,您将其添加到原始数组而不是副本。您可以通过添加以下调试代码来看到这一点:

            Debug.WriteLine(object.ReferenceEquals(DstParent[0], DstChild)); //prints False
    

    解决这个问题的简单方法是避免创建无论如何都完全没有必要的 Children 对象:

            var parentObj = new JObject();
    
            var parentArray = new JArray();
            parentObj.Add("1", parentArray);
    
            var childArray = new JArray();
            parentArray.Add(childArray);
    
            var grandChild = new JObject();
            grandChild.Add("Age", 15);
            childArray.Add(grandChild);
    

    【讨论】:

    • 感谢您的出色回答。来自 javascript,将对象添加到多个父级不会克隆该对象。计划是,创建功能,水平做事,例如。为所有的父母或所有的孩子。因此我也将对象添加到这些对象中......
    • 你告诉我,我应该对 c# 有更深入的了解,而不是像 javascript 那样尝试使用 c#。
    • 谢谢,有点不同,但这帮助我最终解决了添加嵌套对象的问题,而无需反序列化整个事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    相关资源
    最近更新 更多