我有一个看起来像这样的JSON:
[
{
"type":"car",
"types":[
{
"type":"ferrari",
"types":[
{
"type":"big",
"count":5
},
{
"type":"small",
"count":1
}
]
},
{
"type":"volvo",
"types":[
{
"type":"big",
"count":2
}
]
}
]
},
{
"type":"bike",
"types":[
{
"type":"Ducati",
"types":[
{
"type":"small",
"count":1
}
]
}
]
}
]
这就像一个“分组依据”,但嵌套在一起。我想将其转换为不嵌套的。 像这样:
[
{
"types":[ "car", "ferrari", "big" ],
"count":5
},
{
"types":[ "car", "ferrari", "small" ],
"count":1
},
{
"types":[ "car", "volvo", "big" ],
"count":2
},
{
"types":[ "bike", "ducati", "small" ],
"count":1
}
]
由于它是一个递归函数,所以我陷入了困境,但是由于我需要为每个组合创建一个JObject
而变得很复杂。实际上更加复杂,因为我不知道答案的嵌套程度。我知道没有types
属性时要停下来。
我正在尝试使用JObjects
来做到这一点。
答案 0 :(得分:4)
这是我的处理方式:
将JSON解析为JArray
,然后将SelectTokens
与递归下降操作符..
一起使用以查找所有count
令牌。每个对象都有一个结果对象。
创建一个新的JArray
来容纳结果对象。
对于每个count
令牌:
a)沿着祖先链走,从每个级别的type
收集JObject
值到新的JArray
中。 (您将需要颠倒它们的顺序,以便它们从上到下而不是从下到上出现在数组中。)
b)将计数和类型数组组装到新的JObject
中,并将其添加到结果数组中。
最后,将结果JArray
转换回JSON字符串。
这是代码中的样子:
var counts = JArray.Parse(json).SelectTokens("..count");
var array = new JArray();
foreach (var count in counts)
{
var types = count.Ancestors()
.OfType<JObject>()
.Select(o => (string)o["type"])
.Reverse();
var result = new JObject(
new JProperty("types", new JArray(types)),
new JProperty("count", count)
);
array.Add(result);
}
json = array.ToString();
此处的工作演示:https://dotnetfiddle.net/uI2Bzt
如果您喜欢简洁的代码,则可以在“一行”中完成所有操作:
json = new JArray(
JArray.Parse(json)
.SelectTokens("..count")
.Select(c =>
new JObject(
new JProperty("types",
new JArray(
c.Ancestors()
.OfType<JObject>()
.Select(o => (string)o["type"])
.Reverse()
)
),
new JProperty("count", c)
)
)
).ToString();
答案 1 :(得分:0)
首先,您的json无效。
这是有效的:
[
{
"type":"car",
"types":[
{
"type":"volvo",
"types":[
{
"type":"big",
"count":2
}
]
}
]
},
{
"type":"bike",
"types":[
{
"type":"Ducati",
"types":[
{
"type":"small",
"count":1
}
]
}
]
}
]
使用Json.NET将对象反序列化为此类:
public class MasterClass
{
public TypesClass[] Property1 { get; set; }
}
public class TypesClass
{
public string type { get; set; }
public Type[] types { get; set; }
}
public class Type
{
public string type { get; set; }
public Types[] types { get; set; }
}
public class Types
{
public string type { get; set; }
public int count { get; set; }
}
反序列化:
DataSet dsSalesOrders = JsonConvert.DeserializeObject<DataSet>(response.Content);
然后使用LINQ,您可以在每个子集上使用SelectMany将其添加到结果中。