【问题标题】:Using Linq to select into an object with children from Json使用 Linq 从 Json 中选择具有子对象的对象
【发布时间】:2016-01-27 19:00:03
【问题描述】:

我是新手 C# 开发人员,并且是 Linq 的新手,但我试图弄清楚如何将嵌套的子对象从 Linq 查询中获取到对象中。我可以得到主/根对象。

这是我目前的代码和我正在使用的 Json 文件。请注意,如果 Json 出现格式错误,我会手动从 Json 中删除一些文本。

class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.processJson();
        Console.ReadLine();
    }

    public void processJson()
    {
        JObject jobject = JObject.Parse(this.getSampleOrderJsonText());

        // QUESTION IS IN THIS BLOCK OF CODE
        var orders =
            from p in jobject["resource"]["items"].Children()["resource"]
            select new orderHeader
            {
                orderNo = (string)p["orderNo"],
                status = (string)p["status"]
                // How do I fill "lines" and its child object "lines.lineDetails"?
                // lines =
            };

        foreach (orderHeader orderList in orders)
        {
            Console.WriteLine(orderList.orderNo + " " + orderList.status);
        }
    }
    public class orderHeader
    {
        public string orderNo { get; set; }
        public string status { get; set; }
        public List<orderLine> lines { get; set; }
    }
    public class orderLine
    {
        public string sku { get; set; }
        public int quantity { get; set; }

        public List<orderLineDetail> lineDetails { get; set; }
    }

    public class orderLineDetail
    {
        public int productId { get; set; }
        public string serialNumber { get; set; }
    }

    public string getSampleOrderJsonText()
    {
        return "{Entire Json Text}"; // This returns all the JsonText
    }
}

这是我的(已编辑)Json:

{
    "status": 200,
    "message": "Successful",
    "resource": {
        "offset": 0,
        "total": 1,
        "previous": null,
        "next": null,
        "items": [{
            "resource": {
                "orderNo": "#6255.1",
                "lastUpdatedDate": "2016-01-21T17:39:36-08:00",
                "status": "completed",
                "vendorId": null,
                "vendorExternalId": null,
                "id": 153357642,
                "items": {
                    "resource": {
                        "offset": 0,
                        "total": 3,
                        "previous": null,
                        "next": null,
                        "items": [{
                            "resource": {
                                "sku": "796430390315",
                                "quantity": 2,
                                "serialNumbers": {
                                    "resourceLocation": null,
                                    "resource": {
                                        "offset": 0,
                                        "total": 2,
                                        "previous": null,
                                        "next": null,
                                        "items": [{
                                            "resourceLocation": null,
                                            "resource": {
                                                "orderId": 153357642,
                                                "productId": 3525462,
                                                "serialNumber": "T8-0139062"
                                            }
                                        }, {
                                            "resourceLocation": null,
                                            "resource": {
                                                "orderId": 153357642,
                                                "productId": 3525462,
                                                "serialNumber": "T8-0139063"
                                            }
                                        }]
                                    }
                                },
                                "productId": 3525462,
                                "orderId": 153357642,
                                "ordered": 2,
                                "shipped": 1
                            }
                        }, {
                            "resource": {
                                "sku": "796430390322",
                                "quantity": 2,
                                "commercialInvoiceValue": 0,
                                "serialNumbers": {
                                    "resourceLocation": null,
                                    "resource": {
                                        "offset": 0,
                                        "total": 2,
                                        "previous": null,
                                        "next": null,
                                        "items": [{
                                            "resourceLocation": null,
                                            "resource": {
                                                "orderId": 153357642,
                                                "productId": 3525472,
                                                "serialNumber": "T8-0140454"
                                            }
                                        }, {
                                            "resourceLocation": null,
                                            "resource": {
                                                "orderId": 153357642,
                                                "productId": 3525472,
                                                "serialNumber": "T8-0140478"
                                            }
                                        }]
                                    }
                                },
                                "productId": 3525472,
                                "orderId": 153357642,
                                "ordered": 2,
                                "shipped": 1
                            }
                        }, {
                            "resourceLocation": null,
                            "resource": {
                                "sku": "796430390346",
                                "quantity": 1,
                                "commercialInvoiceValue": 0,
                                "serialNumbers": {
                                    "resourceLocation": null,
                                    "resource": {
                                        "offset": 0,
                                        "total": 1,
                                        "previous": null,
                                        "next": null,
                                        "items": [{
                                            "resourceLocation": null,
                                            "resource": {
                                                "orderId": 153357642,
                                                "productId": 3525482,
                                                "serialNumber": "T8-0141520"
                                            }
                                        }]
                                    }
                                },
                                "productId": 3525482,
                                "orderId": 153357642,
                                "ordered": 1,
                                "shipped": 1
                            }
                        }]
                    }
                }
                "options": {
                    "resourceLocation": null,
                    "resource": {
                        "warehouseId": 13,
                        "warehouseRegion": "CHI",
                        "carrierCode": "FDX"
                    }
                }
                "shipTo": {
                    "resource": {
                        "email": "none@nowhere.com",
                        "name": "First Last",
                        "company": "Company, Inc",
                        "address1": "123 South Street",
                        "address2": "",
                        "address3": "",
                        "city": "Chicago",
                        "state": "IL",
                        "postalCode": "60652",
                        "country": "US",
                        "phone": "5555551234"
                    }
                }
                "pricing": {
                    "resourceLocation": null,
                    "resource": {
                        "shipping": 20.76,
                        "packaging": 0.88,
                        "insurance": 9,
                        "handling": 5.25,
                        "total": 35.89
                    }
                }
            }
        }]
    }
}

编辑: 工作代码!这是最好的方法吗?如果子元素不存在怎么办?

public void processJson()
{
    JObject jobject = JObject.Parse(this.getSampleOrderJsonText());

    var orders =
        from p in jobject["resource"]["items"].Children()["resource"]
        select new orderHeader
        {
            orderNo = (string)p["orderNo"],
            status = (string)p["status"],

            lines = (
                from nestedChildren in p["items"]["resource"]["items"].Children()["resource"]
                select new orderLine
                {
                    sku = (string)nestedChildren["sku"],
                    quantity = (int)nestedChildren["quantity"]
                })
        };

    foreach (orderHeader orderList in orders)
    {
        Console.WriteLine(orderList.orderNo + " " + orderList.status);
        if (orderList.lines != null)
        {
            foreach (orderLine line in orderList.lines.ToList())
            {
                Console.WriteLine("-->{0}: {1}", line.sku, line.quantity);
            }
        }
    }
}

【问题讨论】:

  • 为什么不使用嵌套的 linq 查询? lines = from nestedChildren in p ... select ... where
  • 我不知道你能做到这一点。我会玩它,看看我能做什么。
  • 我刚刚用我认为正确的嵌套选择更新了我的代码,但我收到了一个错误。我觉得我总体上是对的,但我缺少一些简单的东西?
  • 我已经成功了!有没有更好的方法来写我的声明?

标签: c# json linq data-structures json.net


【解决方案1】:

如果有更好的方法来编写某个查询,这个问题肯定几乎接近哲学。有不同的方法吗?是的,而且很多!

linq 的 select/from 语法当然很大程度上受到 SQL 的启发,作为一种声明性范例,它具有许多优点和缺点,例如与纯粹的命令式类 C 查询相比。

SQL 风格的 Linq:

  • 更少的教学开销(您不太关心数据类型定义和过程)
  • 它们可以更直接地查看所查询的数据
  • 尤其是查询嵌套会导致可怕且低效的语句,因为它们很快就会变得计算复杂

扩展方法Linq:

类似:

    var MyQuery = MyDataStructure.Where( data => data.property == mySearchProperty )
                                 .Distinct()
                                 .Select( data => data.CustomerID );
  • 更轻松、更隐蔽地集成到 C 风格的方法中
  • 非常适合用 C 风格编写会产生大量开销的快速语句
  • 如果做错了会变得非常低效

C 样式查询:

  • 通常由多个嵌套的 for 循环组成
  • 对实际查询数据的方式提供最大程度的控制
  • 快速为变量和结构定义产生大量开销
  • 如果您想在查询期间添加指令,效率会高很多
  • 如果您比编译器更了解如何并行化它(例如使用 Parallel.Foreach),效率会非常高
  • 通常不太容易阅读,因为与类似 sql 的查询相比,所需的数据模式在结构中隐藏得更深

另一种在云中流行的非常大数据和非常高并行化的方法是 NO-SQL 语法;然而这是一个独立的话题。

对于您的具体情况,我不得不承认,我并不真正了解您的数据是如何构成的——尤其是

p["items"]["resource"]["items"].Children()["resource"]

让我很困惑,看起来很不寻常。 但是只要你得到你想要的数据并且你的代码是可读和可维护的,你就不会在这里出错。除非您有大量数据或时间问题等特定条件,否则您的查询对我来说似乎非常好。

【讨论】:

  • 很棒的信息。我喜欢Extension method Linq,但如何避免使用字符串文字? mySearchProperty 是一个字符串文字还是命名它使它像一个对象?
  • 您仍然处于表达式内方法的常规范围内。它是一个 lambda 表达式, => 之后的所有内容 - 出于所有意图和目的 - 都是一个方法体。因此 mySearchProperty 基本上可以是您可以访问的任何内容 - 字符串、变量、方法等。欲了解更多信息,请查看msdn.microsoft.com/en-us/library/bb397687.aspx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-07
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多