反序列化动态JSON C#

时间:2017-01-13 19:05:19

标签: c# json deserialization

我需要反序列化以下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"
  }

订单数量以及每个订单中的商品数量都是未知的。

我已尝试制作订单列表并动态循环和JsonConvert.DeserializeObject()然后将每个添加到列表中,但这并不能说明动态项目和项目最终等于null。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

这可以使用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"]);
    }
}

为了完整起见,还要将代码反序列化为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);
    }
}

我会说,对于这两个,我必须设置断点并检查对象,看看我必须使用什么以及如何获得这些数据。 &#34;字典&#34;与数组相比,C#中的样式对象更加笨拙。我确实通过this answer找到了另一种方法。虽然最详细,也是最一致的跨物体等级。

//"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"]);
    }
}

通过使用此模式,您应该能够获取任何JToken,将其转换为IDictionary<string, JToken>,然后使用Key以一致的方式处理其内容以获取属性名称和Value的内容(你也会投射到IDictionary,这样你就可以根据需要下降对象。)