我是 C# 开发人员新手,也是 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);
}
}
}
}
是否有更好的方法来编写某个查询的问题当然几乎与哲学接壤。但是,这样做的方法是否不同?是的,而且很多!
当然,linq 的 select/from 语法在很大程度上受到 SQL 的启发,作为一种声明式范式,它有许多优点和缺点,例如与纯粹的命令式 C 类查询相比。
SQl-style Linq:
- 更少的教学开销(你不太关心数据类型定义和过程)
- 它们可以更直接地查看所查询的数据
- 特别是查询嵌套会导致可怕和低效的语句,因为它们很快就会变得计算复杂
扩展方法林克:
像这样:
var MyQuery = MyDataStructure.Where( data => data.property == mySearchProperty )
.Distinct()
.Select( data => data.CustomerID );
- 更轻松、更不显眼地集成到 C 型方法中
- 非常适合快速语句,如果用 C 风格编写会产生很多开销
- 如果做错了,可能会变得疯狂低效
C 样式查询:
- 通常由多个嵌套的 for 循环组成
- 提供对数据实际查询方式的最大控制
- 快速产生变量和结构定义的大量开销 如果要
- 在查询期间添加指令,效率会高得多
- 如果您比编译器更了解如何并行化它(例如使用 Parallel.Foreach),则可以非常高效
- 通常不太容易阅读,因为所需的数据模式隐藏在结构的更深处,而不是类似sql的查询
在云中流行的另一种用于非常大数据和非常高的Parallization的方法是NO-SQL语法;然而,这是一个自己的主题。
对于您的具体情况,我不得不承认,我真的不了解您的数据是如何构建的 - 尤其是
p["items"]["resource"]["items"].Children()["resource"]
让我感到困惑,似乎很不寻常。但是,只要您获得所需的数据并且您的代码是可读的和维护的,您就不会在这里出错。除非您有特定条件,例如大量数据或时间问题,否则您的查询对我来说似乎完全没问题。