1

How can I query (to see if a property exists) and enumerate (the array property) found within a complex JSON object using using JSON.NET in C# ?

I am receiving a complex JSON object from an API with a variable number/type of properties.

I keep reading the JSON.Net Documentation, reviewing samples, etc. but not gotten far and am lost in JObject, JArray, JToken, using dynamic, etc...

I want to find the pageResponses.scriptOutput property, verify it contains and .items[] array and then enumerate/iterate the array.

Edit

I made progress and found typo in JSON data example.

But how can I query/enumerate the child objects using key names, e.g.(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 sample below trimmed down for brevity)

{
  "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
      }
    ]
  }
}
4
  • 1
    You can create a class hierarchy and for any property you don't want to deserialise you can use dynamic. If you want to go through the hierarchy you will need to use a recursive function. Commented May 6, 2016 at 15:11
  • 1
    Another important note, if you are validating JSON, then you can use the JSON.Net validator against a scheme that you create. Look here Commented May 6, 2016 at 15:12
  • 1
    Look at the parse method in this documentation Commented May 6, 2016 at 15:14
  • 1
    I would seriously look in json schema because that sounds like exactly what you're asking for: I want to find the pageResponses.scriptOutput property, verify it contains Commented May 6, 2016 at 15:16

2 Answers 2

2

I suggest creating a proxy class (I used 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; }
}

Then deserialize it:

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);
        }
    }
}
Sign up to request clarification or add additional context in comments.

9 Comments

This helps little, how to actually check for and enumerate the array?
I updated the answer. Is it more clear now? You can use the debugger and inspect the object's structure to help you write the code that handles it.
What is the namespace for RootObject? I can't find it anywhere in JSON.NET or .NET docs online.
Include only the types you need then. No need to add all classes/properties you are not interested in.
Thanks Bruno! This works like a charm in only 9 lines of code. And sorry man I didn't see RootObject in your example (had to scroll down duh!). I created just the classes I need and your advice worked great. 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); } } }
|
0

I do this with a couple of Extension Methods and I use JsonConvert.DeserializeObject.

Code snippets below.

Usage

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

In the snippet above I check a property exists, then I assign it to a .Net type, in this case an object array. Though it can be any type so long as it's sane.

Extension Methods

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];
}

Quick, easy and to the point!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.