首页 > 解决方案 > C#动态对象,根据字符串路径修改属性

问题描述

用例在概念上非常简单。我收到一个 json 有效负载,它在根级别具有两个属性:

  1. instructions
  2. base

指令是我应该应用于基本 json 对象的指令集。

例如 - 根据下面的有效载荷,

输入有效载荷:

{
    "instructions": [
        {
            "patchedPath": "defaultWidget.widgets",
            "patchedValue": false,
        }
    ],
    "base": {
        "defaultWidget": {
            "hash": "ktocle2l0u527",
            "layout": "6|6",
            "managerId": "defaultWidget",
            "widgets": [
                {
                    "managerId": "defaultWidget",
                    "widgetId": "invCreateWid7",
                    "type": "standard",
                    "manifestPath": "nexxe.standard-section@0.0.0-next.11",
                    "defaultInputManifestPath": "nexxe.input@0.0.1-alpha.49",
                    "title": "scannedInvoice",
                    "children": [
                        {
                            "name": "tom"
                        }
                    ],
                    "hash": "ktocle2lrgps9",
                    "directives": ""
                }
            ]
        }
    }
}

结果应该是:

{    
    "base": {
        "defaultWidget": {
            "hash": "ktocle2l0u527",
            "layout": "6|6",
            "managerId": "defaultWidget",
            "widgets": false
        }
    }
}

代码:

var stringPayload = "{    \"instructions\": [        {            \"patchedPath\": \"defaultWidget.widgets\",            \"patchedValue\": false,        }    ],    \"base\": {        \"defaultWidget\": {            \"hash\": \"ktocle2l0u527\",            \"layout\": \"6|6\",            \"managerId\": \"defaultWidget\",            \"widgets\": [                {                    \"managerId\": \"defaultWidget\",                    \"widgetId\": \"invCreateWid7\",                    \"type\": \"standard\",                    \"manifestPath\": \"nexxe.standard-section@0.0.0-next.11\",                    \"defaultInputManifestPath\": \"nexxe.input@0.0.1-alpha.49\",                    \"title\": \"scannedInvoice\",                    \"children\": [                        {                            \"name\": \"tom\"                        }                    ],                    \"hash\": \"ktocle2lrgps9\",                    \"directives\": \"\"                }            ]        }    }}";
var parsedPayload = JsonConvert.DeserializeObject(stringPayload);
var baseJ = parsedPayload.GetType().GetProperty("instructions").GetValue(parsedPayload, null);
string jsonString = JsonConvert.SerializeObject(parsedPayload);

我坚持最初的步骤,我得到:

System.NullReferenceException:“对象引用未设置为对象的实例。”

System.Type.GetProperty(...) 返回 null。

这就是 QuickWatch 所说的:

在此处输入图像描述

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

解决方案


DeserializeObject在这种情况下,返回的内容是JObject从一开始就可以转换为:

var parsedPayload = (JObject) JsonConvert.DeserializeObject(stringPayload);

然后抓取指令和目标来改变:

var instructions = (JArray) parsedPayload["instructions"]; // cast to JArray
var result = parsedPayload["base"];

然后我们可以查看说明并应用它们:

foreach (var instruction in instructions) {
    // grab target path and value
    var targetPath = (string) ((JValue)instruction["patchedPath"]).Value;
    var targetValue = (JValue)instruction["patchedValue"];
    // temp variable to traverse the path
    var target = result;
    foreach (var part in targetPath.Split('.')) {
        target = target[part];
    }
    // replace the value
    target.Replace(targetValue);
}

现在结果包含应用指令的基础内容。


推荐阅读