【问题标题】:How to Query and Enumerate complex JSON object using JSON.Net in C#如何在 C# 中使用 JSON.Net 查询和枚举复杂的 JSON 对象
【发布时间】:2016-05-06 15:08:33
【问题描述】:

如何在 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
      }
    ]
  }
}

【问题讨论】:

  • 您可以创建一个类层次结构,对于您不想反序列化的任何属性,您可以使用dynamic。如果要遍历层次结构,则需要使用递归函数。
  • 另一个重要说明,如果您正在验证 JSON,那么您可以针对您创建的方案使用 JSON.Net 验证器。看here
  • 看看这个documentation中的parse方法
  • 我会认真查看 json 架构,因为这听起来正是您所要求的:I want to find the pageResponses.scriptOutput property, verify it contains

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


【解决方案1】:

我建议创建一个代理类(我使用了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);
        }
    }
}

【讨论】:

  • 这个帮助不大,如何实际检查和枚举数组?
  • 我更新了答案。现在更清楚了吗?您可以使用调试器并检查对象的结构来帮助您编写处理它的代码。
  • RootObject 的命名空间是什么?我在 JSON.NET 或 .NET 在线文档中的任何地方都找不到它。
  • 只包括你需要的类型。无需添加您不感兴趣的所有类/属性。
  • 谢谢布鲁诺!这就像只用 9 行代码的魅力。抱歉,我在您的示例中没有看到 RootObject (不得不向下滚动!)。我只创建了我需要的课程,你的建议很有效。 var obj = JsonConvert.DeserializeObject&lt;RootObject&gt;(json); if (obj != null &amp;&amp; obj.pageResponses != null){ foreach (var pageResponse in obj.pageResponses){ if (pageResponse.scriptOutput == null)continue; foreach (var item in pageResponse.scriptOutput.items){ Console.WriteLine(item); } } }
【解决方案2】:

我用几个扩展方法来做这件事,我使用 JsonConvert.DeserializeObject。

下面的代码 sn-ps。

用法

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

在上面的 sn-p 中,我检查了一个属性是否存在,然后我将它分配给一个 .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];
}

快速、简单、重点突出!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多