【问题标题】: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 是动态的,由用户提供。有很多属性,在执行代码之前我不知道它们的名称。字段名称和值均由用户提供。

【问题讨论】:

标签: c# linq json.net linq-to-objects dynamic-linq


【解决方案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);
    

    【讨论】:

    • 我需要使用字符串谓词/过滤器。字段的名称和值都是由用户提供的,所以这对我没有帮助,抱歉。
    猜你喜欢
    • 2021-06-24
    • 2015-10-03
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    相关资源
    最近更新 更多