我正在尝试将动态JSON(从API)反序列化为正确的对象,但是某些项目没有类型。在示例JSON中,“ fulfillment”属性具有值“ F1”和“ F2”,并且可能具有更多值(问题1)。其中,项目属性具有产品订购信息,但没有以产品名称(即“ 03.64.0005_11_10”)开头的项目类型,该名称可以是成千上万个选项(问题二)。 如何反序列化此JSON以填充正确的对象?我尝试了Json.net的RestCharp,但是我总是卡在无法动态读取和填充的产品属性上。
我尝试了以下答案,但没有成功:
How I deserialize a dynamic json property with RestSharp in C#? Deserialize JSON into C# dynamic object?
你能帮我吗?
"billingAddress": {
"zip": "64001340",
"state": "PI",
"number": "3443",
"status": "ACTIVE",
"firstName": "Fulano",
"telephone": {
"type": "billing",
"number": "88112244"
},
"neighbourhood": "Centro"
},
"clientId": "cliente3",
"documents": [
{
"type": "cpf",
"number": "12345678901"
}
],
"fulfillments": {
"F1": {
"id": "F1",
"orderId": "4017116",
"channelId": "channel2",
"clientId": "cliente3",
"locationId": "708",
"shipment": {
"method": "Economica",
"carrierName": "Transportadora"
},
"status": "CANCELED",
"type": "SHIPMENT",
"enablePrePicking": false,
"items": {
"03.64.0005_11_10": {
"sku": "03.64.0005_11_10",
"quantity": 0,
"stockType": "PHYSICAL",
"orderedQuantity": 1,
"returnedQuantity": 0,
"canceledQuantity": 1,
"itemType": "OTHER",
"presale": false,
"enablePicking": true
},
"18.06.0220_48_2": {
"sku": "18.06.0220_48_2",
"quantity": 0,
"stockType": "PHYSICAL",
"orderedQuantity": 1,
"returnedQuantity": 0,
"canceledQuantity": 1,
"itemType": "OTHER",
"presale": false,
"enablePicking": true
}
}
},
"F2": {
"id": "F2",
"orderId": "4017116",
"channelId": "channel2",
"clientId": "cliente3",
"locationId": "003",
"operator": {
"id": "5188",
"name": "Loja da Vila"
},
"ownership": "oms",
"shipment": {
"method": "Economica",
"carrierName": "Transportadora"
},
"status": "SHIPPING_READY",
"type": "SHIPMENT",
"enablePrePicking": true,
"items": {
"18.04.1465_01_3": {
"sku": "18.04.1465_01_3",
"quantity": 1,
"stockType": "PHYSICAL",
"orderedQuantity": 1,
"returnedQuantity": 0,
"canceledQuantity": 0,
"itemType": "OTHER",
"presale": false,
"enablePicking": true
},
"18.16.0630_13_10": {
"sku": "18.16.0630_13_10",
"quantity": 1,
"stockType": "PHYSICAL",
"orderedQuantity": 1,
"returnedQuantity": 0,
"canceledQuantity": 0,
"itemType": "OTHER",
"presale": false,
"enablePicking": true
}
}
}
},
"createdAt": "2019-06-08T21:41:12.000Z",
"updatedAt": "2019-06-08T21:41:12.000Z"
}
To
public class BillingAddress
{
public string zip { get; set; }
public string state { get; set; }
public string number { get; set; }
public string status { get; set; }
public string firstName { get; set; }
public Telephone telephone { get; set; }
public string neighbourhood { get; set; }
}
public class Fulfillment
{
public string id { get; set; }
public string orderId { get; set; }
public string channelId { get; set; }
public string clientId { get; set; }
public string locationId { get; set; }
public Shipment shipment { get; set; }
public string status { get; set; }
public string type { get; set; }
public bool enablePrePicking { get; set; }
public List<Item> items { get; set; }
}
public class Item
{
public string sku { get; set; }
public int quantity { get; set; }
public string stockType { get; set; }
public int orderedQuantity { get; set; }
public int returnedQuantity { get; set; }
public int canceledQuantity { get; set; }
public string itemType { get; set; }
public bool presale { get; set; }
public bool enablePicking { get; set; }
}
答案 0 :(得分:0)
是的,这种结构实际上并不意味着可以与JSON一起使用。看起来完成属性应该是这些对象的数组,而不是具有编号的属性。看起来好像是从EDI文件等自动生成的,即使大多数好的转换工具都足够聪明,无法做到这一点。
选项A:查看是否有人为您生成文件可以纠正他们的过程。
选项B:如果不可能,则将您的实现属性设为Dictionary类型,其中,实现是该内部实现对象具有的类。然后,它将“适当地”反序列化它,并为您提供一个字典,您可以使用“ F1”键直至“ FN”来引用,但理想情况下,您将在使用字典时从字典中创建列表或数组。即使顺序很重要,您也总是有id字段供以后排序。
// Property on you deserialization object
public Dictionary<string, Fullfillment> fulfillmentDictionary {get; set;}
// Creating the list for easier use of the data
List<Fullfillment> fulfillments = fulfillmentDictionary.Values.ToList();
类似的逻辑将应用于您的商品列表。
答案 1 :(得分:0)
如果问题仅在于键是动态的,而这些动态键对象的结构是明确定义的,则可以使用Dictionary<string, T>
(而不是List<T>
)来处理动态键。从示例JSON来看,情况就是这样。因此,您需要在根级别为fulfillments
和items
中的fulfillments
提供字典。您的课程应如下所示:
public class RootObject
{
public BillingAddress billingAddress { get; set; }
public string clientId { get; set; }
public List<Document> documents { get; set; }
public Dictionary<string, Fulfillment> fulfillments { get; set; }
public DateTime createdAt { get; set; }
public DateTime updatedAt { get; set; }
}
public class BillingAddress
{
public string zip { get; set; }
public string state { get; set; }
public string number { get; set; }
public string status { get; set; }
public string firstName { get; set; }
public Telephone telephone { get; set; }
public string neighbourhood { get; set; }
}
public class Telephone
{
public string type { get; set; }
public string number { get; set; }
}
public class Document
{
public string type { get; set; }
public string number { get; set; }
}
public class Fulfillment
{
public string id { get; set; }
public string orderId { get; set; }
public string channelId { get; set; }
public string clientId { get; set; }
public string locationId { get; set; }
public Operator @operator { get; set; }
public string ownership { get; set; }
public Shipment shipment { get; set; }
public string status { get; set; }
public string type { get; set; }
public bool enablePrePicking { get; set; }
public Dictionary<string, Item> items { get; set; }
}
public class Operator
{
public string id { get; set; }
public string name { get; set; }
}
public class Shipment
{
public string method { get; set; }
public string carrierName { get; set; }
}
public class Item
{
public string sku { get; set; }
public int quantity { get; set; }
public string stockType { get; set; }
public int orderedQuantity { get; set; }
public int returnedQuantity { get; set; }
public int canceledQuantity { get; set; }
public string itemType { get; set; }
public bool presale { get; set; }
public bool enablePicking { get; set; }
}
然后将JSON反序列化为RootObject
类:
var root = JsonConvert.DeserializeObject<RootObject>(json);
这是一个有效的演示:https://dotnetfiddle.net/xReEQh
答案 2 :(得分:0)
对于具有动态键(即从一个消息更改为另一个消息)的JSON消息,您应该先将其解码为动态C#对象。一个经过解码(大多数JSON解析器都支持它)的用户会枚举每个动态属性,然后将其值转换为POCO,例如Fulfillment,Item等(或继续使用动态对象)。
以下是与您的JSON https://dotnetfiddle.net/U5NfzC一起使用的示例