c# - C#动态对象,根据字符串路径修改属性
问题描述
用例在概念上非常简单。我收到一个 json 有效负载,它在根级别具有两个属性:
instructions
base
指令是我应该应用于基本 json 对象的指令集。
例如 - 根据下面的有效载荷,
- 我应该遍历
defaultWidgets
基本属性中的小部件。 - 然后用 的值完全替换它
patchedValue
。
输入有效载荷:
{
"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 所说的:
解决方案
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);
}
现在结果包含应用指令的基础内容。
推荐阅读
- json - 转换响应实体
到列表 [科特林] - flutter - 任何人都知道我是否可以通过 Flutter Web 以某种方式提供 json 文件?
- javascript - 无法读取 this.sidenav.toggle() 中未定义的属性“切换”;
- data-structures - 如何存储链接切割树?
- c# - 性能不佳的后台服务从队列中出列
- zephyr-rtos - 如何在 zephyr-rtos 项目中添加应用程序单元测试
- css - 停止 flexbox 项目 "flex:1" 占用由子宽度引起的更多空间
- javascript - VueJS + Firebase 身份验证在脚本加载之前无法访问会话
- bootbox - 如何在引导箱提示中仅显示确认按钮?
- node.js - 错误 npm install - node-sass@4.13.1 postinstall: `node scripts/build.js