c# - JSON.NET - 在复杂对象中通过值正则表达式查找 JObject?
问题描述
如何使用正则表达式或其他支持通配符的方法按值在我的反序列化 JSON 中搜索 JObject 的路径?
例如,这是我的 JSON:
{
"type": "AdaptiveCard",
"body": [
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "{item.name}",
"size": "Large",
"weight": "Bolder",
"horizontalAlignment": "Center",
"color": "Accent"
},
{
"type": "Image",
"url": "{item.image}",
"altText": ""
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"horizontalAlignment": "Right",
"items": [
{
"type": "TextBlock",
"text": "{template.other}",
"weight": "Bolder",
"horizontalAlignment": "Right"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "{item.other}"
}
]
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"horizontalAlignment": "Right",
"items": [
{
"type": "TextBlock",
"text": "{template.name}",
"weight": "Bolder",
"horizontalAlignment": "Right"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "{item.name}"
}
]
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"horizontalAlignment": "Right",
"items": [
{
"type": "TextBlock",
"text": "{template.order}",
"weight": "Bolder",
"horizontalAlignment": "Right"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "{item.order}"
}
]
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"horizontalAlignment": "Right",
"items": [
{
"type": "TextBlock",
"text": "{template.family}",
"weight": "Bolder",
"horizontalAlignment": "Right"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "{item.genus}"
}
]
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"horizontalAlignment": "Right",
"items": [
{
"type": "TextBlock",
"text": "{template.species}",
"weight": "Bolder",
"horizontalAlignment": "Right"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "{item.species}"
}
]
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"horizontalAlignment": "Right",
"items": [
{
"type": "TextBlock",
"text": "{template.clade}",
"weight": "Bolder",
"horizontalAlignment": "Right"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "Container",
"items": [
{
"$data": "{item.clade}",
"type": "TextBlock",
"text": "{$data}"
}
]
}
]
}
]
}
]
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0"
}
如何找到包含 {item.name}
JSON.NET 的值的元素的路径?
我已经查看了该SelectToken
方法,但我无法弄清楚如何使它适用于我正在尝试做的事情。
解决方案
如果您使用LINQ to JSON并希望找到JValue
包含该字符串(或更一般地匹配任何正则表达式)的所有值的路径"{item.name}"
,您有几个选择。
假设您的正则表达式如下所示:
var innerValue = Regex.Escape(@"{item.name}");
var regexString = $".*{innerValue}.*"; // Evaluates to .*\{item\.name}.*
你有一些JObject obj
捕获你的 JSON 层次结构。
首先,您可以使用以下方法搜索其值与此表达式匹配的所有字符串值标记JContainer.DescendantsAndSelf()
:
var regex = new Regex(regexString);
var paths = obj.Descendants().OfType<JValue>().Where(v => v.Type == JTokenType.String)
.Where(v => regex.IsMatch((string)v.Value))
.Select(v => v.Path)
.ToList();
其次,您可以使用SelectTokens()
JSONPath正则表达式运算符:
var jsonPath = $"..[?(@ =~ /{regexString}/)]"; // Note that the regex should be delimited by `/` characters.
var paths = obj.SelectTokens(jsonPath)
.Select(v => v.Path)
.ToList();
笔记:
除了简短的文章# JSONPath - XPath for JSON之外,没有 JSONPath 的标准。
..
是 JSONPath“递归下降”运算符。@
表示当前对象。[?( )]
使用“底层脚本引擎”应用过滤器(脚本)表达式。=~
是 Newtonsoft 的正则表达式运算符。它是在 Json.NET 11.0.1中引入的。在 JSONPath 字符串中,正则表达式需要由
/
字符(而不是'
)分隔。鉴于 JSONPath 过滤器表达式没有正式定义,我觉得第一个选项更简单一些。
一旦您选择了一组
JValue
值,您就可以使用JToken.Ancestors()
向上爬上父层次结构来找到最低的父级JObject
。
演示小提琴在这里。
推荐阅读
- windows - 获取由 DrawText[Ex] 解释的 GDI HFONT 行高
- django - 尝试使用模型上传音频文件,但出现“未找到”错误(Django)
- android - 在后台运行 BLE ScanCallback
- python - IP地址字符串提取在Python3中不起作用
- c++ - 为什么不总是使用 ::operator new 而不是 new (甚至不构造)?
- swagger - 招摇加豹猫
- python - 如何在 pandas 的数据透视表函数中聚合索引值?
- discord.py - 如何检查此人是否已经在不和谐中使用过命令?
- typescript - 打字稿使用泛型使用类型键参数从接口获取类型值?
- python - 用不断变化的字符串值填充数组