JSON.net在迭代它们时剥离属性

时间:2014-10-16 21:52:57

标签: c# json json.net

我有一个json字符串,我正在使用JObject.parse(string)解析为JObject。当我这样做时,json字符串中的所有属性和对象都存在,如ToString()方法调用所示。但是只要我调用IEnumerable方法,例如

var _mapping = JObject.parse(json);
var _json = _mapping.ToString();
// _json == json at this poing other than some formating
var map = _mapping["c1-14.10.16"]["mappings"]["applog"]["properties"];
foreach(JToken v in map) { 
    string s = v.ToString();
    // s != corresponding node string of json
}

许多属性只会从v和v的孩子身上消失。

这是json失败的简短片段

{"c1-14.10.16":{"mappings":{"applog":{"properties":{"error":{"properties":{"error":{"properties":{"data":{"properties":{"DisablePrepareForRethrow":{"type":"string","index_analyzer":"standard"},"HelpLink.BaseHelpUrl":{"type":"string","index_analyzer":"standard"},"HelpLink.EvtID":{"type":"string","index_analyzer":"standard"},"HelpLink.EvtSrc":{"type":"string","index_analyzer":"standard"},"HelpLink.LinkId":{"type":"string","index_analyzer":"standard"},"HelpLink.ProdName":{"type":"string","index_analyzer":"standard"},"Microsoft.ServiceBus":{"type":"string","index_analyzer":"standard"},"length":{"type":"integer"}}}}}}}}}}}}

"c1-14.10.16".mappings.applog.properties.error.properties.error.properties.data.properties中唯一可识别的属性是length。其他任何属性都没有得到承认。

我做错了什么使它剥离了其他属性?

2 个答案:

答案 0 :(得分:1)

属性在那里 - 但是比你的代码所期望的要低得多。你可以看到如下:

    public static void TestJsonParse(string json)
    {
        try
        {
            var _mapping = JObject.Parse(json);
            var _json = _mapping.ToString();
            // _json == json at this poing other than some formating

            var map = _mapping["c1-14.10.16"]["mappings"]["applog"]["properties"];
            map.WritePropertiesToConsole();

            Debug.Assert(map.Count() == 1); // No assert because the properties aren't here.

            var subMap = _mapping["c1-14.10.16"]["mappings"]["applog"]["properties"]["error"]["properties"]["error"]["properties"]["data"]["properties"];
            subMap.WritePropertiesToConsole();

            Debug.Assert(subMap.Count() == 8); // no assert - the properties are all here.
            Debug.Assert(_mapping["c1-14.10.16"]["mappings"]["applog"]["properties"]["error"]["properties"]["error"]["properties"]["data"]["properties"]["Microsoft.ServiceBus"]["index_analyzer"].ToString() == "standard"); // no assert
        }
        catch (Exception ex)
        {
            Debug.Assert(false, ex.ToString());  // No exception, no assert.
        }
    }

    public static void WritePropertiesToConsole(this JToken subMap)
    {
        int iToken = 0;
        Console.WriteLine(string.Format("Tokens for {0}: {1} found", subMap.Path, subMap.Count()));
        foreach (JToken v in subMap)
        {
            string s = v.ToString();
            Console.WriteLine(string.Format("Token {0}: {1}", iToken++, s));
        }
    }

这是控制台输出:

Tokens for c1-14.10.16.mappings.applog.properties: 1 found
Token 0: "error": {
  "properties": {
    "error": {
      "properties": {
        "data": {
          "properties": {
            "DisablePrepareForRethrow": {
              "type": "string",
              "index_analyzer": "standard"
            },
            "HelpLink.BaseHelpUrl": {
              "type": "string",
              "index_analyzer": "standard"
            },
            "HelpLink.EvtID": {
              "type": "string",
              "index_analyzer": "standard"
            },
            "HelpLink.EvtSrc": {
              "type": "string",
              "index_analyzer": "standard"
            },
            "HelpLink.LinkId": {
              "type": "string",
              "index_analyzer": "standard"
            },
            "HelpLink.ProdName": {
              "type": "string",
              "index_analyzer": "standard"
            },
            "Microsoft.ServiceBus": {
              "type": "string",
              "index_analyzer": "standard"
            },
            "length": {
              "type": "integer"
            }
          }
        }
      }
    }
  }
}

Tokens for c1-14.10.16.mappings.applog.properties.error.properties.error.properties.data.properties: 8 found
Token 0: "DisablePrepareForRethrow": {
  "type": "string",
  "index_analyzer": "standard"
}
Token 1: "HelpLink.BaseHelpUrl": {
  "type": "string",
  "index_analyzer": "standard"
}
Token 2: "HelpLink.EvtID": {
  "type": "string",
  "index_analyzer": "standard"
}
Token 3: "HelpLink.EvtSrc": {
  "type": "string",
  "index_analyzer": "standard"
}
Token 4: "HelpLink.LinkId": {
  "type": "string",
  "index_analyzer": "standard"
}
Token 5: "HelpLink.ProdName": {
  "type": "string",
  "index_analyzer": "standard"
}
Token 6: "Microsoft.ServiceBus": {
  "type": "string",
  "index_analyzer": "standard"
}
Token 7: "length": {
  "type": "integer"
}

属性就在那里,完全符合问题中提供的JSON字符串中指定的深度。所以JSON.net并没有从提供的示例中删除任何内容。您可以使用http://jsonformatter.curiousconcept.com/清楚地查看层次结构:

enter image description here

如果您将问题描述更改为如下:“给定一些JSON,如何递归查找具有多个子属性的名为'properties'的子属性”,您可以这样做,改编自{{ 3}}:

    static IEnumerable<JToken> FindProperties(JToken root)
    {
        return root.WalkNodes().Where(n =>
        {
            var _parent = n.Parent as JProperty;
            if (_parent != null && _parent.Name == "properties")
            {
                if (n.Count() > 1)
                    return true;
            }
            return false;
        });
    }

    public static IEnumerable<JToken> WalkNodes(this JToken node)
    {
        if (node.Type == JTokenType.Object)
        {
            yield return (JObject)node;

            foreach (JProperty child in node.Children<JProperty>())
            {
                foreach (var childNode in child.Value.WalkNodes())
                    yield return childNode;
            }
        }
        else if (node.Type == JTokenType.Array)
        {
            foreach (JToken child in node.Children())
            {
                foreach (var childNode in child.WalkNodes())
                    yield return childNode;
            }
        }
    }

然后,测试它:

            var _properties = FindProperties(_mapping);
            var list = _properties.ToArray();
            Debug.Assert(list.Length == 1 && list[0] == subMap); // no assert   

答案 1 :(得分:0)

问题似乎是您发布的json无效。

在尝试编辑帖子以便json格式化时,我使用的网站正确识别了JSON字符串中的错误。

Go here,然后将您的JSON粘贴到那里,您就会看到问题:

enter image description here