2017-02-10 41 views
1

我想通过使用Json.NET和System.Linq.Dynamic将复杂的json对象匹配到用户定义的过滤器/谓词。这里是我的代码:我如何使用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("[email protected]", "Jane Doe").Any(); 
Console.WriteLine(isMatch); 

这使我对与Where语句来行错误:

“名称”存在类型没有属性或字段“对象”

如果我改为使用匿名对象,则用此替换第二行:

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

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

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

+0

这可以帮助:http://stackoverflow.com/questions/18734996/how-to-use-linq-with-dynamic-collections –

+0

['SelectToken'](http://www.newtonsoft.com/ json/help/html/QueryJsonSelectTokenJsonPath.htm)使用通配符“*”运算符可以满足您的需求。请参阅[在JObject层次结构中按名称搜索特定的JToken](https://stackoverflow.com/a/29782523/3744182)。 – dbc

回答

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"); 
+0

我的需求是通过一个字符串谓词来查询json-string内的一个对象,所以你是对的,这不会帮助我。 – Espo

+0

@Espo我真的了解你,但如果你仍然想考虑只使用Json,你可以再次查看我的答案。 – meJustAndrew

0
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); 
+0

字段的名称和值都由用户提供,所以这不会帮助我,对不起。 – Espo

+0

你知道你可以使用varibles吗? –

+0

现在好吗? –

0

编辑

谢谢您的意见,这实际上是发挥作用。 对不起有点迟到的答案,但也许它会有所帮助。

下面完整的测试与动态参数名称和参数值的工作原理:

 // 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); 
+0

我需要使用一个字符串谓词/过滤器。字段的名称和值由用户提供,所以这不会帮助我,对不起。 – Espo

0

阅读的答案,也是别人的帖子后,我创造了这个解决方案:

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; 
} 

希望它可以帮助别人。