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

Posted

技术标签:

【中文标题】System.Linq.Dynamic.Core - 查询嵌套对象【英文标题】:System.Linq.Dynamic.Core - querying nested objects 【发布时间】:2021-10-02 13:59:32 【问题描述】:

我有一个 JSON 文件,我将其反序列化为一个在基本结构级别具有以下内容的对象:

--- 网站

----- 网站产品

---------产品名称

---------数量

---------价格

----------等等。等等

我需要/希望能够动态查询此结构(Site/SiteProducts 只是我需要查询的许多类似对象的一个​​示例)并且一直在尝试让 Dynamic LINQ 工作。

此 LINQ 语句为我提供了与给定产品匹配的数量总和的输出:

json.Sites.Select(Function(s) s.SiteProducts.Where(Function(sp) sp.ProductName = "Widget").Select(Function(spd) spd.Quantity).Sum)

但是,我无法弄清楚相应的动态 LINQ。我认为这可能有效:

jsonObj.Select("new (Sites.Select(SiteProducts).Where(it.ProductName=""Widget"").Select(Quantity).Count())")

但是没有,因为 siteproducts 不包含 ProductName。

动态 LINQ 甚至可以做到这一点吗?我看过动态 lambda 表达式,但它们看起来相当复杂。我想我只需要知道我是否遗漏了一些明显的东西(比如在我的动态选择/位置中轻松拥有 lambda 函数的能力)还是这不可能?

谢谢你:-)

【问题讨论】:

使用动态的JObject:newtonsoft.com/json/help/html/… 感谢@GHDevOps,但我不确定这是否有帮助 - 所有这一切都会给我一个 JObject 而不是我的根对象的强类型版本。还是我错过了什么? 你必须下定决心。您想要在运行时确定的动态对象还是在编译时确定的强类型对象?如果前者使用动态 linq 或只是动态对象。如果后者使用带有 ORM 的强类型类。 谢谢@GHDevOps,也许我的问题没用好,但这不是关于它是动态对象还是强类型对象,而是关于能够动态查询该对象。最后我走了一条不同的路,在 Newtonsoft 中使用 JSONPath 和 Linq 库能够解决我的问题。无论如何,谢谢,我必须给个提示,因为您指向 JObject 的链接让我走上了正确的道路:-) 【参考方案1】:

由于不清楚您是要动态反序列化还是要在此处使用已知类,所以这里有几个示例

    从类中创建一个 json 字符串 反序列化到类 反序列化为 JObject
void Main()

    var root = new ROOT()
        Price= 22.33M,
        Quantity = 2,
        ProductName = "Test",
        SiteProducts =  "Prod 1", "Prod 2" ,
        Sites = new List<Site>()  new Site() Name = "Test Site", URL = "http://google.com"
    ;
    var JSONstr = JsonConvert.SerializeObject(root).Dump();
    //deserialize to ROOT class
    var JObjclass = JsonConvert.DeserializeObject<ROOT>(JSONstr).Dump("ROOT CLASS");
    //deserialize to anonimus JObject
    var JObj = JsonConvert.DeserializeObject<JObject>(JSONstr).Dump();
    
    JObj["Sites"][0]["Name"].ToString().Dump("");
    
    


public class ROOT

    public List<Site> Sites  get; set; 

    public List<string> SiteProducts  get; set; 

    public string ProductName  get; set; 

    public int Quantity  get; set; 

    public decimal Price  get; set; 
    public ROOT()
    
        Sites = new List<Site>();
        SiteProducts = new List<string>();
        Quantity = 0;
        Price = 0;
    


public class Site

    public string Name  get; set; 
    public string URL  get; set; 



  "Sites": [
    
      "Name": "Test Site",
      "URL": "http://google.com"
    
  ],
  "SiteProducts": [
    "Prod 1",
    "Prod 2"
  ],
  "ProductName": "Test",
  "Quantity": 2,
  "Price": 22.33

【讨论】:

感谢@Power Mouse 的回复,但我认为我没有以足够具体的方式提出我的问题 - 这不是关于能够序列化或反序列化,而是关于能够动态查询结果对象(无论是什么)。我最终使用了 JSONPath,并将为将来发现这篇文章的其他人提供答案(包括我自己!)【参考方案2】:

最后,我最终使用了一些从其中一个 cmets 指向 Newtonsoft 库中的 JObject 对象的指针,并且发现了使用 JSONPath 动态查询对象的能力。这解决了我的问题(没有动态 Linq 库,据我所知,它不允许您查询嵌套数组对象)。

更多信息请点击此处:https://www.newtonsoft.com/json/help/html/QueryJsonSelectTokenJsonPath.htm

还有一个有效的例子:

jObj.SelectToken("$.Sites[*].SiteProducts[?(@.ProductName == 'Widget')].Quantity")

感谢指导 :)

【讨论】:

以上是关于System.Linq.Dynamic.Core - 查询嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章

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

什么都2020了,LINQ查询你还在用表达式树

EF Core 2.0 中的动态访问表