解析没有反射对象的复杂JSON?

时间:2012-03-14 10:38:07

标签: c# .net json json.net

我正在使用一个API来输出具有许多属性(包括子对象)的JSON对象。到目前为止,我在C#中为JSON找到的所有示例都假设.Net对象已被序列化为JSON,并且可以反序列化回.Net对象。

我正在尝试找到一个解决方案,我可以将JSON读入某个通用对象,然后我可以通过从通用对象中选择值来手动将值分配给我的业务对象属性。

可能类似于ADO.Nets Datables和DataRows,您可以将列名称传递给DataRow对象并获取列的值。这可能有点过于先进,但基本上我希望能够通过迭代它们来读取JSON对象,并通过传递属性名称从对象中选择值。这意味着我不会将所有属性反序列化到我的业务对象中,我将从JSON对象中获取特定属性并将其值分配给业务对象的属性。

这样做的好方法是什么?

以下是从API输出的两个对象的示例:

{
  "appt": [
    {
      "d": 1331717080000, 
      "id": "112115", 
      "inv": [
        {
          "comp": [
            {
              "alarm": [
                {
                  "action": "DISPLAY", 
                  "desc": [
                    {}
                  ], 
                  "trigger": [
                    {
                      "rel": [
                        {
                          "m": 5, 
                          "neg": true, 
                          "related": "START"
                        }
                      ]
                    }
                  ]
                }
              ], 
              "apptId": "112115", 
              "calItemId": "112115", 
              "ciFolder": "112111", 
              "class": "PUB", 
              "compNum": 0, 
              "d": 1331717080000, 
              "desc": [
                {
                  "_content": ""
                }
              ], 
              "descHtml": [
                {
                  "_content": "<html><body></body></html>"
                }
              ], 
              "e": [
                {
                  "d": "20120314T130000", 
                  "tz": "Pacific/Auckland", 
                  "u": 1331683200000
                }
              ], 
              "fb": "B", 
              "fba": "B", 
              "isOrg": true, 
              "loc": "", 
              "method": "PUBLISH", 
              "name": "Test Appt", 
              "noBlob": true, 
              "or": {
                "a": "liam@url.com", 
                "d": "Liam Smith", 
                "url": "liam@url.com"
              }, 
              "rsvp": false, 
              "s": [
                {
                  "d": "20120314T090000", 
                  "tz": "Pacific/Auckland", 
                  "u": 1331668800000
                }
              ], 
              "seq": 0, 
              "status": "CONF", 
              "transp": "O", 
              "uid": "aa2e4fe4-c636-4660-ae92-3e7041fe5669", 
              "url": "", 
              "x_uid": "aa2e4fe4-c636-4660-ae92-3e7041fe5669"
            }
          ], 
          "compNum": 0, 
          "id": 112114, 
          "seq": 0, 
          "type": "appt", 
          "tz": [
            {
              "daylight": [
                {
                  "hour": 2, 
                  "min": 0, 
                  "mon": 9, 
                  "sec": 0, 
                  "week": -1, 
                  "wkday": 1
                }
              ], 
              "dayname": "NZDT", 
              "dayoff": 780, 
              "id": "Pacific/Auckland", 
              "standard": [
                {
                  "hour": 3, 
                  "min": 0, 
                  "mon": 4, 
                  "sec": 0, 
                  "week": 1, 
                  "wkday": 1
                }
              ], 
              "stdname": "NZST", 
              "stdoff": 720
            }
          ]
        }
      ], 
      "l": "112111", 
      "rev": 72672, 
      "s": 0, 
      "uid": "aa2e4fe4-c636-4660-ae92-3e7041fe5669"
    }, 
    {
      "d": 1331717176000, 
      "id": "112117", 
      "inv": [
        {
          "comp": [
            {
              "alarm": [
                {
                  "action": "DISPLAY", 
                  "desc": [
                    {}
                  ], 
                  "trigger": [
                    {
                      "rel": [
                        {
                          "m": 5, 
                          "neg": true, 
                          "related": "START"
                        }
                      ]
                    }
                  ]
                }
              ], 
              "apptId": "112117", 
              "calItemId": "112117", 
              "ciFolder": "112111", 
              "class": "PUB", 
              "compNum": 0, 
              "d": 1331717176000, 
              "desc": [
                {
                  "_content": ""
                }
              ], 
              "descHtml": [
                {
                  "_content": "<html><body></body></html>"
                }
              ], 
              "e": [
                {
                  "d": "20120315T120000", 
                  "tz": "Pacific/Auckland", 
                  "u": 1331766000000
                }
              ], 
              "fb": "B", 
              "fba": "B", 
              "isOrg": true, 
              "loc": "", 
              "method": "PUBLISH", 
              "name": "test 2", 
              "noBlob": true, 
              "or": {
                "a": "liam@url.com", 
                "d": "Liam Smith", 
                "url": "liam@url.com"
              }, 
              "rsvp": false, 
              "s": [
                {
                  "d": "20120315T100000", 
                  "tz": "Pacific/Auckland", 
                  "u": 1331758800000
                }
              ], 
              "seq": 0, 
              "status": "CONF", 
              "transp": "O", 
              "uid": "4081f711-9742-42bd-a5dc-8bc9ddc3305d", 
              "url": "", 
              "x_uid": "4081f711-9742-42bd-a5dc-8bc9ddc3305d"
            }
          ], 
          "compNum": 0, 
          "id": 112116, 
          "seq": 0, 
          "type": "appt", 
          "tz": [
            {
              "daylight": [
                {
                  "hour": 2, 
                  "min": 0, 
                  "mon": 9, 
                  "sec": 0, 
                  "week": -1, 
                  "wkday": 1
                }
              ], 
              "dayname": "NZDT", 
              "dayoff": 780, 
              "id": "Pacific/Auckland", 
              "standard": [
                {
                  "hour": 3, 
                  "min": 0, 
                  "mon": 4, 
                  "sec": 0, 
                  "week": 1, 
                  "wkday": 1
                }
              ], 
              "stdname": "NZST", 
              "stdoff": 720
            }
          ]
        }
      ], 
      "l": "112111", 
      "nextAlarm": 1331758500000, 
      "rev": 72674, 
      "s": 0, 
      "uid": "4081f711-9742-42bd-a5dc-8bc9ddc3305d"
    }
  ]
}

2 个答案:

答案 0 :(得分:4)

如果您使用的是Json.Net,则可以使用dynamic关键字。以下是使用json字符串的示例代码。

dynamic obj = JsonConvert.DeserializeObject(jsonstr);
Console.WriteLine("{0} {1}", obj.appt[0].inv[0].comp[0].method, obj.appt[1].id);

foreach (var appt in obj.appt)
{
    Console.WriteLine("{0} {1}", appt.inv[0].comp[0].method, appt.id);
}

如果您使用的是framerork&lt; 4.0,更丑陋的用法也是可能的

JObject obj = (JObject)JsonConvert.DeserializeObject(jsonstr);
foreach (var appt in obj["appt"])
{
    Console.WriteLine("{0} {1}", appt["inv"][0]["comp"][0]["method"], appt["id"]);
}

答案 1 :(得分:0)

您可以使用标准Dictionary<string, object>类将JSON反序列化为JavaScriptSerializer。所有子复杂对象也将自动反序列化为嵌套的Dictionary<string, object>对象,因此如果您需要从JSON的深层访问某些变量,那么您可以随后将所有父对象强制转换为嵌套的Dictionary<string, object>并遍历必要的领域。