首页 > 解决方案 > 如何递归遍历c#中的动态嵌套json

问题描述

如果 dataGeneratorType 是范围,则该值可以是 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
    }
}

标签: c#asp.net.netjsonasp.net-core

解决方案


请试试这个:

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 fiddle


推荐阅读