Home > Software engineering >  How to access multiple groups of nested JSON elements in C#?
How to access multiple groups of nested JSON elements in C#?

Time:11-03

I have a JSON being received from a public API that follows the structure below.

   [
     {
"ID": "12345",
"company": [
  {
    "contract_ID": "abc5678",
    "company": [
      {
        "company_name": "HelloWorld",
        "company_logo": "HW",
        "invested": "2000"
      }
    ]
  },
  {
    "contract_ID": "67891",
    "company": [
      {
        "company_name": "GoodBye",
        "company_logo": "GB",
        "invested": "500"
      }
    ]
  },
  {
    "contract_ID": "32658",
    "company": [
      {
        "company_name": "YesNo",
        "company_logo": "YN",
        "invested": "1500"
      }
    ]
  }
]
   }
     ]

I've tried several different methods of parsing, whether it be JTokens/JArrays or various classes. Something like the following allows me to access the first group of values (company_name, company_logo, invested), but I cannot iterate through to find the other two.

            //receiving the json data
            var responseString = await response.Content.ReadAsStringAsync(); 
            var fullJSON = JsonConvert.DeserializeObject(responseString);
            Debug.Log(fullJSON);

            //trying to parse it down to just the data I need
            JToken token = JToken.Parse("{\"root\":"   responseString   "}");
            Debug.Log(token);
            JArray assets = (JArray)token.SelectToken("root[0].assets");
            Debug.Log(assets);
            JToken dig = JToken.Parse("{\"root\":"   assets   "}");
            Debug.Log(dig);
            JArray assetsNested = (JArray)dig.SelectToken("root[0].assets");
            Debug.Log(assetsNested);

My goal is to extract the contract_ID and then the associated company_name, company_logo, and invested items. For example, abc5678, HelloWorld, HW, and 2000 would be one of the three datasets needed.

CodePudding user response:

The easiest way to deserialize this properly and keep your code maintainable is to use concrete classes. For example:

public sealed class Company
{
    [JsonProperty("contract_ID")]
    public string ContractID { get; set; }

    [JsonProperty("company")]
    public List<CompanyDefinition> CompanyDefinitions { get; set; }
}

public sealed class CompanyDefinition
{
    [JsonProperty("company_name")]
    public string CompanyName { get; set; }

    [JsonProperty("company_logo")]
    public string CompanyLogo { get; set; }

    [JsonProperty("invested")]
    public string Invested { get; set; }
}

public sealed class RootCompany
{
    [JsonProperty("ID")]
    public string ID { get; set; }

    [JsonProperty("company")]
    public List<Company> Company { get; set; }
}

Then, you simply deserialize. For example, if you are pulling from a file you could do this:

using(var sr = new StreamReader(@"c:\path\to\json.json"))
using(var jtr = new JsonTextReader(sr))
{
    var result = new JsonSerializer().Deserialize<RootCompany[]>(jtr);

    foreach(var r in result)
    {
        Console.WriteLine($"Company ID: {r.ID}");
        foreach(var c in r.Company)
        {
            Console.WriteLine($"ContractID: {c.ContractID}");
            foreach(var d in c.CompanyDefinitions)
            {
                Console.WriteLine($"Name: {d.CompanyName}");
                Console.WriteLine($"Invested: {d.Invested}");
                Console.WriteLine($"Company Logo: {d.CompanyLogo}");
            }
        }
    }
}

When something changes with your models, you won't have to dig through lines upon lines of hard-to-read token selection code. You just update your models.

  • Related