Search code examples
c#jsonapijson.netdeserialization

Deserialize nested JSON, C#


I need to deserialize some JSON with this format:

{
  "message": {
    "header": {
      "status_code": 200,
      "execute_time": 0.29062294960022,
      "available": 10000
    },
    "body": {
      "track_list": [
        {
          "track": {
            "track_id": 45085706,
            "track_name": "Love Overdose (Deboa & Hannah Holland Remix)",
            "primary_genres": {
              "music_genre_list": [
                {
                  "music_genre": {
                    "music_genre_name": "Dance"
                  }
                }
              ]
            }
          }
        }
      ]
    }
  }
}

I have these classes which I got from online generator, so I assume they are ok.

 public class Header
{
    public int status_code { get; set; }
    public double execute_time { get; set; }
    public int available { get; set; }
}

public class MusicGenre
{
    public int music_genre_id { get; set; }
    public int music_genre_parent_id { get; set; }
    public string music_genre_name { get; set; }
    public string music_genre_name_extended { get; set; }
    public string music_genre_vanity { get; set; }
}

public class MusicGenreList
{
    public MusicGenre music_genre { get; set; }
}

public class PrimaryGenres
{
    public List<MusicGenreList> music_genre_list { get; set; }
}

public class Track
{
    public int track_id { get; set; }
    public string track_name { get; set; }
    public List<object> track_name_translation_list { get; set; }
    public int track_rating { get; set; }
    public int commontrack_id { get; set; }
    public int instrumental { get; set; }
    public int @explicit { get; set; }
    public int has_lyrics { get; set; }
    public int has_subtitles { get; set; }
    public int has_richsync { get; set; }
    public int num_favourite { get; set; }
    public int album_id { get; set; }
    public string album_name { get; set; }
    public int artist_id { get; set; }
    public string artist_name { get; set; }
    public string track_share_url { get; set; }
    public string track_edit_url { get; set; }
    public int restricted { get; set; }
    public DateTime updated_time { get; set; }
    public PrimaryGenres primary_genres { get; set; }
}

public class TrackList
{
    public Track track { get; set; }
}

public class Body
{
    public List<TrackList> TrackList { get; set; }
}

public class Message
{
    public Header header { get; set; }
    public Body body { get; set; }
}

public class Root
{
    public Message message { get; set; }
}

I tried to deserialize the JSON with this code:

using (StreamReader r = new StreamReader(@"c:\users\xxxx\desktop\1.json"))
{
    string json = r.ReadToEnd();
    var tracks = JsonConvert.DeserializeObject<Track>(json);
}

but I got nothing. I'm new to this; made it with simpler JSON, but I can't figure out how to do it with this code. I want to print a list with just the song names. If anyone can help me I would appreciate it!


Solution

  • There are a couple of problems here:

    1. In your Body class, the TrackList property does not match the JSON. The corresponding property in the JSON is called track_list. The class properties must either exactly match the JSON (ignoring case) or else you need to use a [JsonProperty] attribute on the property to indicate what the JSON name will be. For example:

       public class Body
       {
           [JsonProperty("track_list")] 
           public List<TrackList> TrackList { get; set; }
       }
      
    2. You are attempting to deserialize into the Track class, but you should be deserializing to Root since that represents the root of the JSON.

       var root = JsonConvert.DeserializeObject<Root>(json);       
      

      Once you have deserialized to Root you can "drill down" to print out the tracks.

       foreach (var item in root.message.body.TrackList)
       {
           Console.WriteLine(item.track.track_name);
       }
      

    Fiddle: https://dotnetfiddle.net/JnljGU