2

I am receiving an HttpResponseMessage that looks like this (data redacted):

{ "tracks" : { "href" : "{href_here}", "items" : [ { "album" : { //stuff here }, "name": "{name here}" }, { "album" : { //more stuff here }, "name": "{other name here}" } } } 

My model looks like this:

using System.Text.Json.Serialization; namespace ProjectName.Models { public class Track { [JsonPropertyName("album")] public Album Album { get; set; } [JsonPropertyName("name")] public string Name { get; set; } } } 

I am then attempting to deserialise the response like so:

var response = await _httpClient.GetAsync("URL HERE"); response.EnsureSuccessStatusCode(); return JsonSerializer.Deserialize<IEnumerable<Track>>(await response.Content.ReadAsStringAsync()); 

I would like to retrieve a list of Tracks (which corresponds to items in JSON).

I cannot find a way online to "skip" parent properties and only deserialize a specific child (in this case items). I do not need href (and the other properties that I have removed).

Is there a way to do this?

15
  • You using .Net Core 3.x or .Net 5? Commented Jan 10, 2021 at 23:14
  • 1
    Honestly in .Net 3.1 it's going to be easiest to create wrapper DTOs for the root and tracks objects. Second easiest is to load into a JsonDocument and query it -- but JsonDocument doesn't support JSONPath so there's a little work involved. Most effort would be to write code to manually stream through the JSON tokens until you get what you want using Utf8JsonReader. More trouble that it's worth really. Commented Jan 10, 2021 at 23:23
  • 2
    Why not just create a class, that represents the root object?That would be the most consistent way. You can omit properties you don't need. Commented Jan 10, 2021 at 23:23
  • 1
    I'm not exactly sure what @dbc means, but writing a custom deserializer or brittle XPath is going to cause more work than just generating the classes that correspond to the input JSON and letting your code read rootObject.Tracks.Items. The parser will have to read the JSON anyway. See also stackoverflow.com/questions/34222588/… Commented Jan 10, 2021 at 23:33
  • 1
    @Jessica - in .NET 5 you can deserialize to an anonymous type, as shown in Deserialize anonymous type with System.Text.Json. So you could do (await JsonSerializerExtensions.DeserializeAnonymousTypeAsync(await response.Content.ReadAsStreamAsync(), new { tracks = new { items = default(IEnumerable<Track>) } }))?.tracks?.items; Commented Jan 12, 2021 at 14:31

1 Answer 1

2
using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; namespace StackOverflow { public class Album { } public class Item { [JsonPropertyName("album")] public Album Album { get; set; } [JsonPropertyName("name")] public string Name { get; set; } } public class Tracks { [JsonPropertyName("href")] public string Href { get; set; } [JsonPropertyName("items")] public List<Item> Items { get; set; } } public class Root { [JsonPropertyName("tracks")] public Tracks Tracks { get; set; } } class Program { static void Main(string[] args) { var jsonStr = "{\"tracks\":{\"href\":\"{href_here}\", \"items\" : [{\"album\" : { }, \"name\": \"{name here}\"}]}}"; var root = JsonSerializer.Deserialize<Root>(jsonStr); //Here is your "IEnumerable<Track>" var items = root.Tracks.Items; } } } 

Your model must have such a structure, then it deserialize your data as expected. Then you can use Linq to bring the result to every format you want.

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.