Castiel
Castiel

Reputation: 93

Select part of json with System.text.json

I begin c# and Deserialize Json. In my training I studied Newtonsoft, but I would like to do the same with system.text.json

With this json, I want to select

To make a object list.

https://api.nvidia.partners/edge/product/search?page=1&limit=9&locale=fr-fr&category=GPU&gpu=RTX%203090,RTX%203080%20Ti,RTX%203080,RTX%203070%20Ti,RTX%203070,RTX%203060%20Ti,RTX%203060&gpu_filter=RTX%203090~12,RTX%203080%20Ti~7,RTX%203080~16,RTX%203070%20Ti~3,RTX%203070~18,RTX%203060%20Ti~8,RTX%203060~2,RTX%202080%20SUPER~1,RTX%202080~0,RTX%202070%20SUPER~0,RTX%202070~0,RTX%202060~6,GTX%201660%20Ti~0,GTX%201660%20SUPER~9,GTX%201660~8,GTX%201650%20Ti~0,GTX%201650%20SUPER~3,GTX%201650~17

Class

public class CarteGraphique
{
    public string displayName { get; set; }
    public string prdStatus { get; set; }
    public List<Retailer> retailers { get; set; }
}

With Newtonsoft, I do the following:

Newtonsoft

JObject jsonParse = JObject.Parse(json);

IList<CarteGraphique> products = new List<CarteGraphique>();

IList<JToken> productDetailsParse = jsonParse["searchedProducts"]["productDetails"]
    .Children()
    .Where(n => n["isFounderEdition"].Value<bool>() == true)
    .ToList();
var featuredProductParse = jsonParse["searchedProducts"]["featuredProduct"];


foreach (JToken item in productDetailsParse)
{
    CarteGraphique result = item.ToObject<CarteGraphique>();
    products.Add(result);
}
var featuredProduct = featuredProductParse.ToObject<CarteGraphique>();

products.Add(featuredProduct);



foreach (var item in products)
{
    Console.WriteLine(item.DisplayName);
}

I want to do that with System.Text.Json...but I don't know how select json part "productDetails" for add this in a object list.

System.text.json

var listGpu = new List<CarteGraphique>();

var jsonParse = JsonDocument.Parse(json);

var jsonFilter = jsonParse.RootElement
    .GetProperty("searchedProducts")
    .GetProperty("featuredProduct")
    .GetRawText();

var jsonObj = JsonSerializer.Deserialize<CarteGraphique>(jsonFilter);

listGpu.Add(jsonObj);


foreach (var item in listGpu)
{
    Console.WriteLine(item.displayName);
}

Can you help me please? Documentation is not clear for the beginner that i am.

Upvotes: 8

Views: 6901

Answers (2)

Andrey
Andrey

Reputation: 101

I also have faced the same inconvinieces when moved to JsonDocument. So I have developed a small library to re-create the same behavior JObject had. It allows to navigate domain object model using indexer-like syntax. It is called JsonEasyNavigation, you can find it on github or get from nuget.org.

In your case, the solution could be the following:

List<CarteGraphique> products = new List<CarteGraphique>();

using var jsonDocument = JsonDocument.Parse(json);
var nav = jsonDocument.ToNavigation();

var productDetails = nav["searchedProducts"]["productDetails"].Values
    .Where(x => x["isFounderEdition"].GetBooleanOrDefault())
    .Select(x => x.Map<CarteGraphique>())
    .ToArray();

var featuredProduct = nav["searchedProducts"]["featuredProduct"].Map<CarteGraphique>();

products.AddRange(productDetails);
products.Add(featuredProduct);

JsonDocument have to be transformed into the JsonNavigationElement using ToNavigation() method. I hope you will find it useful.

Upvotes: 1

dbc
dbc

Reputation: 117036

You can emulate the Json.NET logic as follows:

using var jsonParse = JsonDocument.Parse(json); // Be sure to dispose the JsonDocument!

var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };

var products = jsonParse.RootElement
    .GetProperty("searchedProducts") // Get the searchedProducts value
    .GetProperty("productDetails")   // Get the productDetails value
    .EnumerateArray()                // Enumerate its items
    .Where(n => n.GetProperty("isFounderEdition").GetBoolean()) // Filter on those for which isFounderEdition == true
    .Select(n => n.ToObject<CarteGraphique>(options)) // Deserialize to a CarteGraphique
    .ToList();
    
// Add the searchedProducts.featuredProduct item to the list.
var featuredProduct = jsonParse.RootElement
    .GetProperty("searchedProducts")
    .GetProperty("featuredProduct")
    .ToObject<CarteGraphique>(options);

products.Add(featuredProduct);
        

Where ToObject<T>(this JsonElement element, JsonSerializerOptions options = null) is an extension method from this answer to System.Text.Json.JsonElement ToObject workaround:

public static partial class JsonExtensions
{
    public static T ToObject<T>(this JsonElement element, JsonSerializerOptions options = null)
    {
        var bufferWriter = new System.Buffers.ArrayBufferWriter<byte>();
        using (var writer = new Utf8JsonWriter(bufferWriter))
            element.WriteTo(writer);
        return JsonSerializer.Deserialize<T>(bufferWriter.WrittenSpan, options);
    }

    public static T ToObject<T>(this JsonDocument document, JsonSerializerOptions options = null)
    {
        if (document == null)
            throw new ArgumentNullException(nameof(document));
        return document.RootElement.ToObject<T>(options);
    }       
}

Notes:

Demo fiddle here.

Upvotes: 8

Related Questions