可以使用JSONPath搜索不区分大小写的内容吗?

Uwe*_*eim 6 .net json json.net jsonpath

使用SelectToken方法 JSON.NET的选择与令牌JSONPath,我发现没有办法specifiy,搜索应该是不区分大小写。

例如

json.SelectToken("$.maxAppVersion")
Run Code Online (Sandbox Code Playgroud)

无论是否已写入令牌或任何其他大小写形式maxappversion,都应返回匹配的令牌MAXAPPVERSION

我的问题:

是否存在不区分大小写的方式使用JSONPath的正式方法或至少是变通方法?

(我找到的最接近的是针对JSON的Java实现的类似问题

dbc*_*dbc 7

从8.0.2版开始,在Json.NET中未实现此功能。

JSONPath属性名称匹配使用两个类完成:FieldFilter用于简单名称匹配和ScanFilter递归搜索。 FieldFilter具有以下代码,其中oJObject

JToken v = o[Name];
if (v != null)
{
    yield return v;
}
Run Code Online (Sandbox Code Playgroud)

在内部JObject使用a JPropertyKeyedCollection来保存其属性,该属性又使用以下比较器进行属性名称查找:

private static readonly IEqualityComparer<string> Comparer = StringComparer.Ordinal;
Run Code Online (Sandbox Code Playgroud)

因此,它区分大小写。同样,ScanFilter具有:

JProperty e = value as JProperty;
if (e != null)
{
    if (e.Name == Name)
    {
        yield return e.Value;
    }
}
Run Code Online (Sandbox Code Playgroud)

这也是区分大小写的。

JSONPath标准中没有提及不区分大小写的匹配,因此我认为开箱即用就无法获得所需的内容。

解决方法是,您可以为此添加自己的扩展方法:

public static class JsonExtensions
{
    public static IEnumerable<JToken> CaseSelectPropertyValues(this JToken token, string name)
    {
        var obj = token as JObject;
        if (obj == null)
            yield break;
        foreach (var property in obj.Properties())
        {
            if (name == null)
                yield return property.Value;
            else if (string.Equals(property.Name, name, StringComparison.OrdinalIgnoreCase))
                yield return property.Value;
        }
    }

    public static IEnumerable<JToken> CaseSelectPropertyValues(this IEnumerable<JToken> tokens, string name)
    {
        if (tokens == null)
            throw new ArgumentNullException();
        return tokens.SelectMany(t => t.CaseSelectPropertyValues(name));
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将它们与标准SelectTokens调用链接在一起,例如:

var root = new { Array = new object[] { new { maxAppVersion = "1" }, new { MaxAppVersion = "2" } } };

var json = JToken.FromObject(root);

var tokens = json.SelectTokens("Array[*]").CaseSelectPropertyValues("maxappversion").ToList();
if (tokens.Count != 2)
    throw new InvalidOperationException(); // No exception thrown
Run Code Online (Sandbox Code Playgroud)

(相关信息,请参阅Json.NET问题,提供一种执行区分大小写的属性反序列化的方法,该方法要求区分大小写的协定解析器以实现与LINQ-to-JSON区分大小写的一致性。)

  • @KyleDelaney - 自从我回答这个问题以来已经很长时间了,但是 [`GetValue(String, StringComparison)`](https://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Linq_JObject_GetValue_1.htm) 返回一个 **single* * value 而扩展方法返回多个值,这在存在多个仅因大小写不同的属性的情况下可能很有用。 (2认同)