Home > Software engineering >  JSON deserializing nested response
JSON deserializing nested response

Time:05-30

I'm having a novice problem deserializing a response from an API (.NET6, using System.Text.Json). I get the response successfully using this:

    var itemresponse = await response.Content.ReadFromJsonAsync<JSON_Item>();

I get all nested values as expected in "itemresponse", fully visible in the VS debugger. Now I wish to loop through the response and pull out relevant values - seems simple and straightforward...

First issue:

I can pull out values from first level like this:

string test1 = itemresponse.product.title;

However, I cannot get a nested value from the Variant, like this:

string test2 = itemresponse.product.variants.sku;

All properties in "variants" are unknown, and I can not "dot" them in Visual Studio.

Second issue:

I'm trying to loop through all values in the response using this:

foreach (var w in itemresponse.product)
{
    string test = w.vendor;         // Works
    string test2 = w.variants.sku;  // sku not recognizable
}                                                               

I'm aware that my "itemresponse" is not a list, but I would expect to be able to loop through the object anyhow. Beeep.. Not possible. I'm getting this: "foreach cannot operate on variables of type "Product" because "Product" does not contain a public instance or extension definition for "GetEnumerator".

Ok, I make a few changes:

var itemresponse = await response.Content.ReadFromJsonAsync<List<JSON_Item>>();
foreach (var w in itemresponse)
{
    string test = w.product.vendor;     // Works
    string test2 = w.product.variants.sku;  // sku still not recognizable
}                                                               

Trying to run, I get this: JsonException: The JSON value could not be converted to System.Collections.Generic.List`1[Project.Models.JSON_Item]. Path: $ | LineNumber: 0 | BytePositionInLine: 1.

I'm stuck, and I don't know how to get nested values from "variants". Kindly asking for help using "Best practice".

Thanks a lot in advance.

René

Below are the classes i use:

public class JSON_Item
{
    public Product product { get; set; }
}

public class Product
{
    public long? id { get; set; }
    public string title { get; set; }
    public string body_html { get; set; }
    public string vendor { get; set; }
    public List<Variant> variants { get; set; }
}

public class Variant
{
    public long? id { get; set; }
    public long? product_id { get; set; }
    public string? title { get; set; }
    public string? price { get; set; }
    public string? sku { get; set; }
}

Example of response JSON:

{
   "product":{
      "id":6912905806009,
      "title":"This is the title",
      "body_html":"Description here...",
      "vendor":"Cronus Inc.",
      "variants":[
         {
            "id":40775169605817,
            "product_id":6912905806009,
            "title":"Variant 1",
            "price":"899.00",
            "sku":"5710698076083"
         }
      ]
   }
}

EDIT: Will something like nested foreach loops be durable?

foreach (var q in itemresponse.product)
{
    string title = q.product.title;

    foreach (var w in itemresponse.product.variants)
    {
        string test = w.sku;
    }
}

If so, how do I then connect the loops so I make sure variants would be linked to the correct product looping through my JSON object?

I wonder what the "best practice" solution is to this? Guess this is a very common demand for extracting values from nested JSON objects?

CodePudding user response:

For the first (and second issue, but more on that later), you cannot access SKU directly on the list of variants. In your example:

string test1 = itemresponse.product.title;

Works because title is a property of the product object.

string test2 = itemresponse.product.variants.sku;

Does not work because the variants list does not have a SKU property. You would need to access a specific variant object in the variants list to get the SKU. For instance, you could do the following:

foreach (var variant in itemresponse.product.variants) {
    Console.WriteLine(variant.sku);
}

For the second issue, in your examples you are treating an object (both itemresponse and product) as lists and trying to foreach over them. This is not valid. You can only foreach over an iterable data structure such as a list or an array. If you remove the foreach from those code snippets then you're left with the same issue as you had the first time, where you are trying to access a property of a variant object from a list of variants, which is also invalid.

  • Related