首页 > 解决方案 > 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方法,但我无法弄清楚如何使它适用于我正在尝试做的事情。

标签: c#jsonjson.net

解决方案


如果您使用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

演示小提琴在这里


推荐阅读