8

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

  • searchedProducts > featuredProduct AND
  • searchedProducts > productDetails

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.

2
  • System.Text.Json is case-sensitive so you need to use new JsonSerializerOptions { PropertyNameCaseInsensitive = true }, see dotnetfiddle.net/nMaXSh. and JsonSerializer.Deserialize fails. This is why CarteGraphique.PrdStatus is not deserialized successfully. Is that your only problem? It's not clear where you problem is exactly, from your question. Commented Jul 21, 2021 at 20:05
  • Thanks for the answer, sorry bad paste, i edit my class. No it's not that, i just want get "productDetails" and deserialize for add in a list, like my example with Newtonsoft Commented Jul 21, 2021 at 20:20

2 Answers 2

8

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank, It helps me a lot, it's very good to explain. Just a question, why use "using" on parse and webclient on your demo ?
@Castiel - because both are disposable. JsonDocument needs to be disposed as explained in my answer's "Notes". The older WebClient (which I used in the fiddle because it's synchronous) also should be disposed. However, the newer HttpClient should be cached and reused not disposed, see Do HttpClient and HttpClientHandler have to be disposed between requests?.
1

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.

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.