我有一个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
。其他任何属性都没有得到承认。
我做错了什么使它剥离了其他属性?
答案 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/清楚地查看层次结构:
如果您将问题描述更改为如下:“给定一些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)