如何使用 System.Linq.Dynamic 检查 JSON 对象是不是与谓词匹配

Posted

技术标签:

【中文标题】如何使用 System.Linq.Dynamic 检查 JSON 对象是不是与谓词匹配【英文标题】:How can I use System.Linq.Dynamic to check if a JSON object matches a predicate如何使用 System.Linq.Dynamic 检查 JSON 对象是否与谓词匹配 【发布时间】:2017-06-28 22:50:36 【问题描述】:

我正在尝试使用 Json.NET 和 System.Linq.Dynamic 将复杂的 json 对象与用户定义的过滤器/谓词进行匹配。这是我的代码:

var json = @"""Name"":""Jane Doe"",""Occupation"":""FBI Consultant""";
dynamic person = JObject.Parse(json);
var people = new[]  person ;
var isMatch = people.Where("Name=@0", "Jane Doe").Any();
Console.WriteLine(isMatch);

这给了我一个与Where-statement 相关的错误:

“对象”类型中不存在属性或字段“名称”

如果我改用匿名对象,通过用这个替换第二行,它可以正常工作:

var person = new  Name = "Jane Doe", Occupation = "FBI Consultant";

是否有另一种反序列化 json 字符串的方法,可以让我通过字符串谓词查询它以检查 json 对象是否匹配?

EDIT:json-string 和 Where-statement 是动态的,由用户提供。有很多属性,在执行代码之前我不知道它们的名称。字段名称和值均由用户提供。

【问题讨论】:

这可能会有所帮助:***.com/questions/18734996/… SelectToken 使用通配符* 运算符可能会满足您的需求。见Searching for a specific JToken by name in a JObject hierarchy。 【参考方案1】:

将您的 Where 语句替换为:

var isMatch = people.Where(x => x.Name == "Jane Doe").Any();

可以简化为:

var isMatch = people.Any(x => x.Name == "Jane Doe");

这可能不是您想要的,但简单的 System.Linq 可以轻松满足您的需求。

对于您想要动态执行此操作的情况:

var isMatch = people.Any(x => x.GetValue("Name") == "Jane Doe");

【讨论】:

我的需要是通过字符串谓词查询json字符串中的对象,所以你是对的,这对我没有帮助。 @Espo 我真的理解你,但如果你仍然想考虑只使用 Json,你可以再次查看我的答案。【参考方案2】:
var json = @"""Name"":""Jane Doe"",""Occupation"":""FBI Consultant""";
dynamic person = JObject.Parse(json);
var people = new List<object>() person ;
var filedName = "Name";
var searchValue = "Jane Doe";    

var any = people.Any(p => p.GetType().GetProperty(filedName).GetValue(p, null) as string == searchValue);

【讨论】:

字段的名称和值都由用户提供,所以这对我没有帮助,抱歉。 你知道你可以在那里使用变量吗?【参考方案3】:

在阅读了答案和其他帖子后,我创建了这个解决方案:

void Main()

    var json = @"""Name"":""Jane Doe"",""Occupation"":""FBI Consultant"", ""Info"": ""Age"":28, ""Gender"":""Female""";
    Console.WriteLine("Match Name: " + json.JsonMatch("Name", "Jane Doe"));
    Console.WriteLine("Match Age: " + json.JsonMatch("Info.Age", "28"));


public static bool JsonMatch(this string json, string key, string value)

    dynamic obj = JObject.Parse(json);
    var values = obj.PropertyValues();
    foreach (var element in values)
    
        if (element.Path == key)
        
            return element.Value == value;
        
        if (element.Path == null)
        
            foreach (var subelement in element)
            
                if (subelement.Path == key)
                
                    return subelement.Value == value;
                
            
        
    
    return false;

希望它对某人有所帮助。

【讨论】:

【参考方案4】:

编辑

感谢您的 cmets,这实际上有所作为。 抱歉回答晚了一点,但也许它仍然会有所帮助。

以下使用动态参数名称和参数值的完整测试:

        // Given
        var json = @"""Name"":""Jane Doe"",""Occupation"":""FBI Consultant""";
        var person = JObject.Parse(json);
        var people = new[] person;

        // When
        var isMatch = people.Any(p => p.GetValue("Name").Value<string>() == "Jane Doe");

        // Then
        Assert.IsTrue(isMatch);

【讨论】:

我需要使用字符串谓词/过滤器。字段的名称和值都是由用户提供的,所以这对我没有帮助,抱歉。

以上是关于如何使用 System.Linq.Dynamic 检查 JSON 对象是不是与谓词匹配的主要内容,如果未能解决你的问题,请参考以下文章

System.Linq.Dynamic的使用

System.Linq.Dynamic.Core - 查询嵌套对象

System.Linq.Dynamic

使用Dynamic LINQ创建高级查询服务 #yyds干货盘点#

在哪里可以找到 System.Linq.Dynamic dll?

动态 linq:创建生成 JSON 结果的扩展方法