如何在 C# 中递归遍历动态嵌套 json



如果 dataGeneratorType 是 range,则该值可以是 dataGeneratorStart 和 dataGeneratorEnd 之间的任何值。如果 dataGeneratorType 是没有长度属性的数组,则该值将从数组中随机选择一个值,否则它是两个随机选择的等于长度的值。如果它是对象(可以更嵌套(,那么它将再次遵循上述逻辑。但这就是对我来说变得棘手的地方。是否有任何动态方法可以解决C#中的问题。

输入有效负载 JSON

{
"temperature": {
"type": "int",
"dataGeneratorType": "range",
"dataGeneratorStart": -5,
"dataGeneratorEnd": 55
},
"salesAmount": {
"type": "float",
"dataGeneratorType": "array",
"dataGeneratorArray": [
0.51,
13.33,
20.01,
1.54
]
},
"city": {
"type": "string",
"dataGeneratorType": "array",
"dataGeneratorArray": [
"UK",
"Iceland",
"Portugal",
"Spain"
]
},
"relatedTags": {
"type": "array",
"dataGeneratorType": "array",
"dataGeneratorArray": [
"Sport",
"Hardware",
"Cycling",
"Magazines"
],
"length": 2
},
"salesDetail": {
"type": "object",
"dataGeneratorType": "object",
"dataGeneratorValue": {
"VAT": {
"type": "float",
"dataGeneratorType": "range",
"dataGeneratorStart": 0.0,
"dataGeneratorEnd": 20.0
},
"discountAmount": {
"type": "float",
"dataGeneratorType": "array",
"dataGeneratorArray": [
0.10,
0.15,
0.20
]
}
}
}
}

要输出 json:

{
"temperature": 20,
"salesAmount": 20.01,
"city": "Iceland",
"relatedTags": [
"Sport",
"Cycling"
],
"salesDetails": {
"VAT": 15.0,
"discount": 0.1
}
}

请尝试以下操作:

static string TransformJson(string inputPayload)
{
JObject obj = JObject.Parse(inputPayload);
var manipulatedObj = obj.DeepClone();
foreach (var child in obj)
{
var key = child.Key;
var t = child.Value["type"];
JToken genType;
if (!((JObject)child.Value).TryGetValue("dataGeneratorType", out genType))
{
continue; // genType is not found so, continue with next object.
}
var str = genType.Type == JTokenType.String ? genType.ToString().ToLower() : null;
switch (str)
{
case "range":
var r = new Random();
if (((string)t).ToLower() == "float")
{
var s = (float)child.Value["dataGeneratorStart"];
var e = (float)child.Value["dataGeneratorEnd"];
manipulatedObj[key] = r.NextDouble() * e;
}
else
{
var s = (int)child.Value["dataGeneratorStart"];
var e = (int)child.Value["dataGeneratorEnd"];
manipulatedObj[key] = r.Next(s, e);
}
break;
case "array":
var arr = child.Value["dataGeneratorArray"];
JToken lengthToken;
if (!((JObject)child.Value).TryGetValue("length", out lengthToken))
{
lengthToken = 2.ToString();
}
if ((string)t != "array")
{
manipulatedObj[key] = arr.OrderBy(a => a).LastOrDefault();
}
else
{
var count = arr.Count() >= (int)lengthToken ? (int)lengthToken : arr.Count();
var item = new JArray();
foreach (var m in Enumerable.Range(0, count).Select(i => arr[i]))
{
item.Add(m);
}
manipulatedObj[key] = item;
}
break;
case "object":
var transformJson = TransformJson(child.Value["dataGeneratorValue"].ToString());
manipulatedObj[key] = JObject.Parse(transformJson);
break;
default:
manipulatedObj[key] = child.Value["dataGeneratorValue"];
break;
}
}
return manipulatedObj.ToString(Formatting.Indented);
}

并按如下方式使用它:

var serializeObject =   @"{""temperature"":{""type"":""int"",""dataGeneratorType"":""range"",""dataGeneratorStart"":-5,""dataGeneratorEnd"":55},""salesAmount"":{""type"":""float"",""dataGeneratorType"":""array"",""dataGeneratorArray"":[0.51,13.33,20.01,1.54]},""relatedTags"":{""type"":""array"",""dataGeneratorType"":""array"",""dataGeneratorArray"":[""Sport"",""Hardware"",""Cycling"",""Magazines""],""length"":2},""salesDetail"":{""type"":""object"",""dataGeneratorType"":""object"",""dataGeneratorValue"":{""VAT"":{""type"":""float"",""dataGeneratorType"":""range"",""dataGeneratorStart"":0.0,""dataGeneratorEnd"":20.0},""discountAmount"":{""type"":""float"",""dataGeneratorType"":""array"",""dataGeneratorArray"":[0.1,0.15,0.2]}}}}";
Console.WriteLine(serializeObject);
var outputJson = TransformJson(serializeObject);
Console.WriteLine(System.Environment.NewLine + "Modified Json = " + System.Environment.NewLine);
Console.WriteLine(outputJson);

我只是在一个函数中添加了所有内容,但您可以拆分为多个函数和/或类以使单元测试更容易。

这是dotnet小提琴。

这是针对您的问题的逻辑要点。要解析嵌套的 json,您必须使用递归语句并对每一层进行处理。

public Void Traverse(string myJsonString){
var jObj = JObject.Parse(jsonString);
foreach (var item in jObj)
{
if(item.Value["dataGeneratorType"].ToString().Equals("range")){
Console.WriteLine("Do some logic");
}
else if(item.Value["dataGeneratorType"].ToString().Equals("array")){
if(item.Value["length"] != null){
Console.WriteLine("Length is present do more logic");
}
else
{
Console.WriteLine("No length property present do more logic");
}

}
else if(item.Value["dataGeneratorType"].ToString().Equals("object")){
Console.WriteLine("It's an object");
Console.WriteLine(item.Value["dataGeneratorValue"]);
foreach (var nestedItem in item.Value["dataGeneratorValue"]){
Console.WriteLine("Nested Item");
Console.WriteLine(nestedItem);
//Recursive function call
Traverse(nestedItem.Value)//pass in as a json string
}

}

}
}
}

最新更新