如何在C#中使用JSON.Net查询和枚举复杂的JSON对象

时间:2016-05-06 15:08:33

标签: c# json linq json.net linq-to-json

如何使用C#中的JSON.NET查询(查看属性是否存在)和枚举(数组属性)在复杂JSON对象中找到的内容?

我从具有可变数量/类型属性的API接收复杂的JSON对象。

我一直在阅读the JSON.Net Documentation,查看样本等,但没有得到很多,我在JObject,JArray,JToken,使用动态等方面迷失了......

我想找到pageResponses.scriptOutput属性,验证它包含和.items[]数组,然后枚举/迭代数组。

修改

我取得了进展并在JSON数据示例中找到了拼写错误。

但是如何使用键名查询/枚举子对象,例如(item.location, item.timestamp)?

string json = File.ReadAllText(@"Output.json");
JObject jObj = JObject.Parse(json);

IList<JToken> items = jObj["pageResponses"][0]["scriptOutput"]["items"].ToList();
foreach (JToken item in items){
    Console.WriteLine(item["location"]);
}
/*** Console Output ***/
// Austin, TX
// Anaheim, CA
// Adams, MN
// Barstow, CA

var varItems = from o in jObj["pageResponses"][0]["scriptOutput"]["items"].ToList() select o;

foreach (var item in varItems){
    Console.WriteLine(item["timestamp"]);
}
/*** Console Output ***/
// 2016 - 05 - 03 19:53
// 2016 - 05 - 04 04:10
// 2016 - 05 - 04 08:18
// 2016 - 05 - 01 12:26

(为简洁起见,下面的JSON示例已经过修剪)

{
  "meta": {
    "outputAsJson": true,
    "backend": {
      "os": "linux",
      "id": "10.240.0.3_2",
      "requestsProcessed": 8
    }
  },
  "pageResponses": [
    {
      "pageRequest": {
        "renderType": "script",
        "outputAsJson": true
      },
      "frameData": {
        "name": "",
        "childCount": 1
      },
      "events": [
                  {
                    "key": "navigationRequested",
                    "time": "2016-05-06T13:43:30.344Z"
                  },
                  {
                    "key": "navigationRequested",
                    "time": "2016-05-06T13:43:31.131Z"
                  }
      ],
      "scriptOutput": {
        "items": [
          {
            "location": "Austin, TX",
            "timestamp": "2016-05-03 19:53",
            "title": "User Login"
          },
          {
            "location": "Anaheim, CA",
            "timestamp": "2016-05-04 04:10",
            "title": "User Logout"
          },
          {
            "location": "Adams, MN",
            "timestamp": "2016-05-04 08:18",
            "title": "User Login"
          },
          {
            "location": "Barstow, CA",
            "timestamp": "2016-05-01 12:26",
            "title": "User Logout"
          }
        ]
      },
      "statusCode": 200
    }
  ],
  "statusCode": 200,
  "content": {
    "name": "content.json",
    "encoding": "utf8"
  },
  "originalRequest": {
    "pages": [
      {
        "renderType": "script",
        "outputAsJson": true
      }
    ]
  }
}

2 个答案:

答案 0 :(得分:2)

我建议创建一个代理类(我使用json2csharp):

public class Backend
{
    public string os { get; set; }
    public string id { get; set; }
    public int requestsProcessed { get; set; }
}

public class Meta
{
    public bool outputAsJson { get; set; }
    public Backend backend { get; set; }
}

public class PageRequest
{
    public string renderType { get; set; }
    public bool outputAsJson { get; set; }
}

public class FrameData
{
    public string name { get; set; }
    public int childCount { get; set; }
}

public class Event
{
    public string key { get; set; }
    public string time { get; set; }
}

public class ScriptOutput
{
    public List<object> items { get; set; }
}

public class PageRespons
{
    public PageRequest pageRequest { get; set; }
    public FrameData frameData { get; set; }
    public List<Event> events { get; set; }
    public ScriptOutput scriptOutput { get; set; }
    public int statusCode { get; set; }
}

public class Content
{
    public string name { get; set; }
    public string encoding { get; set; }
}

public class Page
{
    public string renderType { get; set; }
    public bool outputAsJson { get; set; }
}

public class OriginalRequest
{
    public List<Page> pages { get; set; }
}

public class RootObject
{
    public Meta meta { get; set; }
    public List<PageRespons> pageResponses { get; set; }
    public int statusCode { get; set; }
    public Content content { get; set; }
    public OriginalRequest originalRequest { get; set; }
}

然后反序列化:

var obj = JsonConvert.DeserializeObject<RootObject>(json);
if (obj != null && obj.pageResponses != null)
{
    foreach (var pageResponse in obj.pageResponses)
    {
        if (pageResponse.scriptOutput == null)
            continue;

        foreach (var item in pageResponse.scriptOutput.items)
        {
            Console.WriteLine(item);
        }
    }
}

答案 1 :(得分:0)

我使用几个扩展方法执行此操作,并使用JsonConvert.DeserializeObject。

以下代码段。

<强>用法

ExpandoObject data = JsonConvert.DeserializeObject<ExpandoObject>(jsonString);
if(data.HasProperty("propertyToCheck"))
{
   object[] objects = data.Get<object[]>("propertyToCheck");
}

在上面的代码片段中,我检查属性是否存在,然后将其分配给.Net类型,在这种情况下是一个对象数组。虽然它可以是任何类型,只要它是理智的。

扩展方法

public static bool HasProperty(this ExpandoObject value, string property)
{
    bool hasProp = false;
    if (((IDictionary<String, object>)value).ContainsKey(property))
    {
        hasProp = true;
    }
    return hasProp;
}

public static T Get<T>(this ExpandoObject value, string property)
{
    return (T)((IDictionary<String, dynamic>)value)[property];
}

快速,简单,重点!