简体   繁体   中英

Read json without knowing the key in c#

I want to parse the below mentioned JSON and get all values of screenshot.thumbnailUrl . But below are my constraints:

Not all nodes have screenshot. In this example only "weather" and "entities" have it.

I do not know the node names. In this example I didn't know that there would be a node named "weather" or "entities". These nodes are auto generated based on the query i made to get the json.

There are two possible places where screenshot can be present. (1) In the child of rootobject eg weather.screenshot (2) In all values of child of rootobject eg entities.value[0].screenshot, entities.value[1].screenshot etc.

{   "_type": "SearchResponse",   "queryContext": {},   "webPages": {}, "entities": {
    "queryScenario": "DominantEntity",
    "value": [
      {
        "_type": "Place",
        "id": "https://www.someapi.com/api/v6/#Entities.0",
        "screenshot": {
          "thumbnailUrl": "http://Screenshot_URL_I_Want",
          "width": 285
        },
        "name": "Seattle",
        "entityPresentationInfo": {},
        "bingId": "5fbba6b8-85e1-4d41-9444-d9055436e473",
        "boundingBox": [],
        "weather": {},
        "timeZone": "Pacific Standard Time"
      }
    ]   },   "images": {},   "weather": {
    "id": "https://www.someapi.com/api/v6/#Weather",
    "screenshot": {
      "thumbnailUrl": "http://Screenshot_URL_I_Want",
       "width": 285
    },
    "location": {},
    "currentWeather": {},
    "dailyForecast": []   },   "rankingResponse": {} }

This is what worked for me... I am looking for a cleaner solution though...

static async void getJobject(string jsonstring)
        {
            JObject response = await JObject.Parse(jsonstring);
            foreach (var node in response.Children())
            {
                Console.WriteLine(node.Path);
                string propertyPath = node.Path + ".screenshot.thumbnailUrl";
                var token = response.SelectToken(propertyPath);

                if (token != null)
                {
                    Console.WriteLine("Check this=> " + token.ToString()); //Prints screenshot URL from weather
                }
                else
                {
                    propertyPath = node.Path + ".value";
                    token = response.SelectToken(propertyPath);
                    if (token != null)
                    {
                        int count = token.Children().Count();
                        for (int i = 0; i < count; i++)
                        {
                            propertyPath = node.Path + ".value" + "[" + i.ToString() + "]" + ".screenshot.thumbnailUrl";
                            var mytoken = response.SelectToken(propertyPath);
                            if (mytoken != null)
                            {
                                Console.WriteLine("Check this=> " + mytoken.ToString()); //Prints screenshot URL from entities
                            }
                        }


                    }
                }

            }
        }

You could use code like this to parse the JSon and recursively iterate through it. You will have to probably refine the logic in the lambda of the call to RecursiveDescent to make it correct and robust for your type of JSON:

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            string json = @"....your JSON ....";

            var node = JToken.Parse(json);

            RecursiveDescent(node, n =>
            {
                JToken url = n["thumbnailUrl"];
                if (url != null && url.Type == JTokenType.String)
                {
                    var nodeWeWant = url?.Parent?.Parent?.Parent?.Parent;

                    Console.WriteLine(nodeWeWant.ToString());
                }
            });
        }

        static void RecursiveDescent(JToken node, Action<JObject> action)
        {
            if (node.Type == JTokenType.Object)
            {
                action((JObject)node);
                foreach (JProperty child in node.Children<JProperty>())
                    RecursiveDescent(child.Value, action);
            }
            else if (node.Type == JTokenType.Array)
            {
                foreach (JToken child in node.Children())
                    RecursiveDescent(child, action);
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM