简体   繁体   English

反序列化动态 JSON C#

[英]Deserialize Dynamic JSON C#

I need to deserialize the following json:我需要反序列化以下 json:

    {
      "1": {
        "oid": "46",
        "order": "SD9999999999999",
        "date": "2015-08-18 14:17:05",
        "item": {
          "0": {
            "guid": "DEF456"
            "price": "100.00"
          },
          "1": {
            "guid": "ABC123",
            "price": "99.99"
          }
        }
      },
      "2": {
        "oid": "765",
        "order": "SD0000000000000",
        "date": "2015-08-18 14:17:05",
        "item": {
          "0": {
            "guid": "GHI789"
            "price": "10.00"
          },
          "1": {
            "guid": "XYZ123",
            "price": "9.99"
          }
       }
    },
    "store": 111,
    "time": "2015-09-01 17:51:22"
  }

The number of orders is unknown as well as the number of items in each order.订单数量以及每个订单中的商品数量未知。

I have tried making a list of orders and dynamically looping through and JsonConvert.DeserializeObject() thhen adding each to the list, but this doesn't account for the items being dynamic and items end up equalling null.我曾尝试制作订单列表并动态循环通过 JsonConvert.DeserializeObject() 然后将每个订单添加到列表中,但这并没有说明项目是动态的,项目最终等于 null。 Any thoughts?有什么想法吗?

This works using JObject/JToken (after fixing the missing , in your json).这可以使用 JObject/JToken(在修复 json 中丢失的,之后)。

var json = System.IO.File.ReadAllText("test.json");
var jobj = Newtonsoft.Json.Linq.JObject.Parse(json);

//exclude "store" and "time"
var orders = jobj.Children().Where(x => x.Path != "store" && x.Path != "time").ToList();

//iterate over orders
foreach (var order in orders)
{
    //"name" of order
    var orderName = order.Path;
    //and contents
    var orderItems = order.First()["item"].ToList();

    foreach (var item in orderItems)
    {
        var itemName = item.Path;
        var itemContents = item.First();

        var guid = (String)itemContents["guid"];
        var price = Double.Parse((String)itemContents["price"]);
    }
}

And for completeness, also code deserializing to a Dictionary<String, dynamic>为了完整起见,还可以将代码反序列化为Dictionary<String, dynamic>

var dynObj = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<String, dynamic>>(json);
var dynOrders = dynObj.Where(x => x.Key != "store" && x.Key != "time").ToList();

foreach (dynamic order in dynOrders)
{
    var orderName = order.Key;
    var orderItems = order.Value.item;

    foreach (var item in orderItems)
    {
        var itemName = item.Name;
        var guid = (String)item.Value.guid;
        var price = Double.Parse((String)item.Value.price);
    }
}

I will say that for both of these, I had to set breakpoints and examine the objects and see what I had to work with and what would work to get that data.我会说,对于这两种情况,我必须设置断点并检查对象,看看我必须使用什么以及获取这些数据的方法。 "Dictionary" style objects are more awkward in C# compared to arrays.与数组相比,“字典”样式的对象在 C# 中更加笨拙。 I did find another way to do this via this answer .我确实通过这个答案找到了另一种方法来做到这一点 While the most verbose, also the most consistent across object levels.虽然最冗长,但在对象级别上也是最一致的。

//"force" to use IDictionary interface
IDictionary<string, JToken> dict = Newtonsoft.Json.Linq.JObject.Parse(json);
var dictOrders = dict.Where(x => x.Key != "store" && x.Key != "time").ToList();

foreach (var order in dictOrders)
{
    var orderName = order.Key;
    var orderProps = (IDictionary<string, JToken>)order.Value;

    var oid = Int32.Parse((String)orderProps["oid"]);
    var orderX = (String)orderProps["order"];
    var date = DateTime.Parse((String)orderProps["date"]);
    var orderItems = (IDictionary<string, JToken>)orderProps["item"];

    foreach (var item in orderItems)
    {
        var itemName = item.Key;
        var itemContents = (IDictionary<string, JToken>)item.Value;

        var guid = (String)itemContents["guid"];
        var price = Double.Parse((String)itemContents["price"]);
    }
}

By using this pattern, you should be able to take any JToken , cast it to a IDictionary<string, JToken> , then deal with its contents in a consistent manner using Key for the property name and Value for the contents (which you would also cast to IDictionary so you can descent the object as far as you need).通过使用此模式,您应该能够获取任何JToken ,将其转换为IDictionary<string, JToken> ,然后使用Key作为属性名称和Value作为内容以一致的方式处理其内容(您也可以转换为IDictionary以便您可以根据需要降低对象)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM