使用Linq从Json中选择带有子节点的对象

时间:2016-01-27 19:00:03

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

我是新手C#dev和更新的Linq,但我正在试图弄清楚如何将Linq查询中的嵌套子对象转换为对象。我可以得到主/根对象。

到目前为止,这是我的代码和我正在使用的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);
            }
        }
    }
}

1 个答案:

答案 0 :(得分: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"]

让我困惑,似乎很不寻常。 但只要您获得所需的数据并且您的代码可读且易于维护,您就不会在这里出错。除非您有特定条件,如大量数据或时间问题,否则您的查询对我来说似乎完全没问题。