How to use the JsonProperty to get the nested property

c#, json, json.net

Solution

Since the `cast` property in the JSON is not inside the top-level object (the movie), and you do not want to introduce an intermediate `Credits` class, then you'll need to use a custom `JsonConverter` to bridge the gap. Here is what the converter might look like:

public class MovieConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Movie));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        Movie movie = jo.ToObject<Movie>();
        movie.Lists = jo.SelectToken("credits.cast").ToObject<List<Actor>>();
        return movie;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

To use the converter, just pass an instance of it to the `JsonConvert.DeserializeObject()` method like this:

Movie movie = JsonConvert.DeserializeObject<Movie>(json, new MovieConverter());

Here is a demo:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {
            ""id"": 550,
            ""original_title"": ""Fight Club"",
            ""credits"": {
                ""cast"": [
                    {
                        ""id"": 819,
                        ""name"": ""Edward Norton"",
                        ""character"": ""The Narrator"",
                        ""order"": 0,
                        ""cast_id"": 4,
                        ""profile_path"": ""/eIkFHNlfretLS1spAcIoihKUS62.jpg""
                    },
                    {
                        ""id"": 287,
                        ""name"": ""Brad Pitt"",
                        ""character"": ""Tyler Durden"",
                        ""order"": 1,
                        ""cast_id"": 5,
                        ""profile_path"": ""/kc3M04QQAuZ9woUvH3Ju5T7ZqG5.jpg""
                    },
                    {
                        ""id"": 1283,
                        ""name"": ""Helena Bonham Carter"",
                        ""character"": ""Marla Singer"",
                        ""order"": 2,
                        ""cast_id"": 6,
                        ""profile_path"": ""/58oJPFG1wefMC0Vj7sFzHPrm67J.jpg""
                    },
                    {
                        ""id"": 7470,
                        ""name"": ""Meat Loaf"",
                        ""character"": ""Robert 'Bob' Paulson"",
                        ""order"": 3,
                        ""cast_id"": 7,
                        ""profile_path"": ""/pwNyXgegO1nlZ8uWT847JM8EjGj.jpg""
                    },
                    {
                        ""id"": 7471,
                        ""name"": ""Zach Grenier"",
                        ""character"": ""Richard Chesler"",
                        ""order"": 4,
                        ""cast_id"": 8,
                        ""profile_path"": ""/jghYiKdNkVehKpiVyE97AWrU9KQ.jpg""
                    }
                ]
            }
        }";

        Movie movie = JsonConvert.DeserializeObject<Movie>(json, new MovieConverter());
        Console.WriteLine(movie.Title + " cast:");
        foreach (Actor actor in movie.Lists)
        {
            string sep = new string('\t', actor.Name.Length > 14 ? 1 : 2);
            Console.WriteLine(actor.Name + sep + actor.CharacterName);
        }
    }
}

Output:

Fight Club cast:
Edward Norton           The Narrator
Brad Pitt               Tyler Durden
Helena Bonham Carter    Marla Singer
Meat Loaf               Robert 'Bob' Paulson
Zach Grenier            Richard Chesler

Problem

I'm trying to Deserialize this JSON code with Json.net. It is information about a specific movie. Everything works as expected, except the `cast` property, which is nested within the `credits` property. I've made a class for the cast called `Actor` and a list of this actor class in my `Movie` class. Here is the JSON: ``` { "id":550, "original_title":"Fight Club", "credits": { "cast": [ { "id":819, "name":"Edward Norton", "character":"The Narrator", "order":0, "cast_id":4, "profile_path":"/eIkFHNlfretLS1spAcIoihKUS62.jpg" }, { "id":287, "name":"Brad Pitt", "character":"Tyler Durden", "order":1, "cast_id":5, "profile_path":"/kc3M04QQAuZ9woUvH3Ju5T7ZqG5.jpg" }, { "id":1283, "name":"Helena Bonham Carter", "character":"Marla Singer", "order":2, "cast_id":6, "profile_path":"/58oJPFG1wefMC0Vj7sFzHPrm67J.jpg" }, { "id":7470, "name":"Meat Loaf", "character":"Robert 'Bob' Paulson", "order":3, "cast_id":7, "profile_path":"/pwNyXgegO1nlZ8uWT847JM8EjGj.jpg" }, { "id":7471, "name":"Zach Grenier", "character":"Richard Chesler", "order":4, "cast_id":8, "profile_path":"/jghYiKdNkVehKpiVyE97AWrU9KQ.jpg" }, { "id":7472, "name":"Richmond Arquette", "character":"Intern", "order":5, "cast_id":9, "profile_path":null }, { "id":7219, "name":"David Andrews", "character":"Thomas", "order":6, "cast_id":10, "profile_path":"/pxmxn29UHW9r6uvLrd7bEwLswlQ.jpg" }, { "id":7473, "name":"Rachel Singer", "character":"Chloe", "order":11, "cast_id":11, "profile_path":null }, { "id":7497, "name":"Holt McCallany", "character":"The Mechanic", "order":20, "cast_id":22, "profile_path":"/hQBfcw9KVszdenlTZTR8AIrSpex.jpg" }, { "id":7498, "name":"Eion Bailey", "character":"Ricky", "order":22, "cast_id":23, "profile_path":"/4MnRgrwuiJvHsfoiJrIUL4TkfoC.jpg" }, { "id":7499, "name":"Jared Leto", "character":"Angel Face", "order":23, "cast_id":24, "profile_path":"/lzQSuu5o0JC9mCncYjVnncSH5lO.jpg" }, { "id":7500, "name":"Peter Iacangelo", "character":"Lou", "order":24, "cast_id":25, "profile_path":null }, { "id":56112, "name":"David Lee Smith", "character":"Walter", "order":19, "cast_id":30, "profile_path":"/xYkMA9AWtUN93KV5hWzlDkcnebB.jpg" }, { "id":1129738, "name":"George Maguire", "character":"Group Leader", "order":7, "cast_id":31, "profile_path":null }, { "id":197790, "name":"Eugenie Bondurant", "character":"Weeping Woman", "order":8, "cast_id":32, "profile_path":null }, { "id":68277, "name":"Christina Cabot", "character":"Group Leader", "order":9, "cast_id":33, "profile_path":"/7UBTv5lW6apPdVLnOqTTBMTJWwY.jpg" }, { "id":202080, "name":"Sydney 'Big Dawg' Colston", "character":"Speaker", "order":10, "cast_id":34, "profile_path":null }, { "id":1172435, "name":"Christie Cronenweth", "character":"Airline Attendant", "order":12, "cast_id":35, "profile_path":null }, { "id":956719, "name":"Tim De Zarn", "character":"Inspector Bird", "order":13, "cast_id":36, "profile_path":null }, { "id":59285, "name":"Ezra Buzzington", "character":"Inspector Dent", "order":14, "cast_id":37, "profile_path":"/dl0SIqpOqS05UpJHKuDQqZTwUvP.jpg" }, { "id":1269622, "name":"Dierdre Downing-Jackson", "character":"Woman on Plane", "order":15, "cast_id":38, "profile_path":null }, { "id":543293, "name":"Bob Stephenson", "character":"Airport Security Officer (as Robert J. Stephenson)", "order":16, "cast_id":39, "profile_path":"/iH86ZmoSGOCnWZ8aycavGdlu3ht.jpg" }, { "id":62846, "name":"Charlie Dell", "character":"Doorman", "order":17, "cast_id":40, "profile_path":"/z0JgZxazJAVlHxLYXWM8eUZlOk8.jpg" }, { "id":530040, "name":"Rob Lanza", "character":"Man in Suit", "order":18, "cast_id":41, "profile_path":null }, { "id":137425, "name":"Joel Bissonnette", "character":"Food Court Maitre D'", "order":21, "cast_id":42, "profile_path":null }, { "id":175120, "name":"Evan Mirand", "character":"Steph", "order":25, "cast_id":43, "profile_path":null }, { "id":169636, "name":"Robby Robinson", "character":"Next Month's Opponent", "order":26, "cast_id":44, "profile_path":null }, { "id":168924, "name":"Lou Beatty Jr.", "character":"Cop at Marla's Building", "order":27, "cast_id":45, "profile_path":null }, { "id":1219497, "name":"Thom Gossom Jr.", "character":"Detective Stern", "order":28, "cast_id":46, "profile_path":null }, { "id":157938, "name":"Valerie Bickford", "character":"Susan, Cosmetics Dealer", "order":29, "cast_id":47, "profile_path":null }, { "id":42824, "name":"Carl Ciarfalio", "character":"Lou's Body Guard (as Carl N. Ciarfalio)", "order":30, "cast_id":48, "profile_path":null }, { "id":40277, "name":"Stuart Blumberg", "character":"Car Salesman", "order":31, "cast_id":49, "profile_path":null }, { "id":1270716, "name":"Todd Peirce", "character":"Man #1 at Auto Shop", "order":32, "cast_id":50, "profile_path":null }, { "id":122805, "name":"Mark Fite", "character":"Man #2 at Auto Shop", "order":33, "cast_id":51, "profile_path":"/9On8A4VRctM8uuaJYE0KaLhDjcw.jpg" }, { "id":35521, "name":"Matt Winston", "character":"Seminary Student", "order":34, "cast_id":52, "profile_path":"/6hGcDyUaewBHdwfmKYp6EP7otRh.jpg" }, { "id":1270720, "name":"Joon Kim", "character":"Raymond K. Hessel (as Joon B. Kim)", "order":35, "cast_id":53, "profile_path":null }, { "id":1010551, "name":"Bennie Moore", "character":"Bus Driver with Broken Nose (as Bennie E. Moore Jr.)", "order":36, "cast_id":54, "profile_path":null }, { "id":1224996, "name":"Lauren Sánchez", "character":"Channel 4 Reporter (as W. Lauren Sanchez)", "order":37, "cast_id":55, "profile_path":null }, { "id":1174793, "name":"Pat McNamara", "character":"Police Commissioner Jacobs", "order":38, "cast_id":56, "profile_path":null }, { "id":1270723, "name":"Tyrone R. Livingston", "character":"Banquet Speaker", "order":39, "cast_id":57, "profile_path":null }, { "id":1113343, "name":"Owen Masterson", "character":"Airport Valet", "order":40, "cast_id":58, "profile_path":null }, { "id":109100, "name":"David Jean Thomas", "character":"Policeman (as David Jean-Thomas)", "order":41, "cast_id":59, "profile_path":null }, { "id":160412, "name":"Paul Carafotes", "character":"Salvator, Winking Bartender", "order":42, "cast_id":60, "profile_path":"/yFRANT8p0D4j4PJclkd1psi5a0J.jpg" }, { "id":145531, "name":"Christopher John Fields", "character":"Proprietor of Dry Cleaners", "order":43, "cast_id":61, "profile_path":"/jTWw4B74VhrPo8AN6Q9jq31eYDD.jpg" }, { "id":182139, "name":"Anderson Bourell", "character":"Bruised Bar Patron #1", "order":44, "cast_id":62, "profile_path":null }, { "id":63537, "name":"Scotch Ellis Loring", "character":"Bruised Bar Patron #2", "order":45, "cast_id":63, "profile_path":"/7Tk72GCd4TLfJj16EvVroEtMv86.jpg" }, { "id":9291, "name":"Michael Shamus Wiles", "character":"Bartender in Halo", "order":46, "cast_id":64, "profile_path":"/upfSW6BGze446iqsZRehzcToNm8.jpg" }, { "id":170315,"name":"Andi Carnick","character":"Hotel Desk Clerk","order":47,"cast_id":65,"profile_path":null},{"id":1270724,"name":"Edward Kowalczyk","character":"Waiter at Clifton's","order":48,"cast_id":66,"profile_path":null},{"id":7140,"name":"Leonard Termo","character":"Desk Sergeant","order":49,"cast_id":67,"profile_path":null},{"id":41352,"name":"Van Quattro","character":"Detective Andrew","order":50,"cast_id":68,"profile_path":null},{"id":140476,"name":"Markus Redmond","character":"Detective Kevin","order":51,"cast_id":69,"profile_path":null},{"id":177175,"name":"Michael Girardin","character":"Detective Walker","order":52,"cast_id":70,"profile_path":null},{"id":74507,"name":"Michael Arturo","character":"BMW Salesman (uncredited)","order":53,"cast_id":71,"profile_path":"/yMm3LVd8tm63B3e3DF415U5qRaI.jpg"},{"id":1194120,"name":"Matt Cinquanta","character":"Fighter (uncredited)","order":54,"cast_id":72,"profile_path":null},{"id":1270725,"name":"Tommy Dallace","character":"Champion Fighter (uncredited)","order":55,"cast_id":73,"profile_path":null},{"id":13925,"name":"Paul Dillon","character":"Irvin (uncredited)","order":56,"cast_id":74,"profile_path":"/6jouXtMcbJ7nTuDNwvaePnqCHTX.jpg"},{"id":552271,"name":"Eddie Hargitay","character":"Chanting Fighter (uncredited)","order":57,"cast_id":75,"profile_path":null},{"id":94561,"name":"Phil Hawn","character":"Banquet Guest (uncredited)","order":58,"cast_id":76,"profile_path":null},{"id":1270726,"name":"Jawara","character":"Fight Patron Saying 'What's going on?' (uncredited)","order":59,"cast_id":77,"profile_path":null},{"id":207609,"name":"Baron Jay","character":"Waiter (uncredited)","order":60,"cast_id":78,"profile_path":null},{"id":154636,"name":"Jim Jenkins","character":"Restaurant Maitre'd (uncredited)","order":61,"cast_id":79,"profile_path":null},{"id":1270727,"name":"Kevin Scott Mack","character":"Passenger Clutching Armrest (uncredited)","order":62,"cast_id":80,"profile_path":null},{"id":1270728,"name":"Trey Ore","character":"Fight Club Patron / Guy #2 in video store (uncredited)","order":63,"cast_id":81,"profile_path":null},{"id":1270729,"name":"Louis Ortiz","character":"Fight Spectator (uncredited)","order":64,"cast_id":82,"profile_path":null},{"id":1270730,"name":"Hugh Peddy","character":"Fight Club Man (uncredited)","order":65,"cast_id":83,"profile_path":null},{"id":1270731,"name":"J.T. Pontino","character":"Fight Club Man (uncredited)","order":66,"cast_id":84,"profile_path":null},{"id":1270732,"name":"Chad Randau","character":"Waiter (uncredited)","order":67,"cast_id":85,"profile_path":null},{"id":133153,"name":"Marcio Rosario","character":"Fighter (uncredited)","order":68,"cast_id":86,"profile_path":null},{"id":962235,"name":"Gregory Silva","character":"Riley Wilde, Fighter (uncredited)","order":69,"cast_id":87,"profile_path":null},{"id":16060,"name":"Brian Tochi","character":"Fight Bully (uncredited)","order":70,"cast_id":88,"profile_path":"/2nAC2ssCFu74zkhg1722WQhArGO.jpg"},{"id":1270733,"name":"Alekxia Valdez","character":"Bar Worker saying \"His name is Robert Paulsen\" (uncredited)","order":71,"cast_id":89,"profile_path":null } ], } } ``` The Movie class: ``` public class Movie { [JsonProperty(PropertyName = "id")] public int ID { get; set; } [JsonProperty(PropertyName = "original_title")] public string Title { get; set; } [JsonProperty(PropertyName = "cast"] public List<Actor> Lists { get; set; } } ``` The Actor class: ``` public class Actor { #region Properties [JsonProperty(PropertyName = "id")] public int ActorId { get; set; } [JsonProperty(PropertyName = "name")] public string Name { get; set; } [JsonProperty(PropertyName = "character")] public string CharacterName { get; set; } [JsonProperty(PropertyName = "order")] public int Order { get; set; } [JsonProperty(PropertyName = "cast_id")] public int CastId { get; set; } [JsonProperty(PropertyName = "profile_path")] public string ProfilePath { get; set; } #endregion } ``` I want to access the `cast` property without making a class called e.g. `credits` to store the list of actors in. I want directly to store list of actors in the `Movie` class. The call for deserialize looks like this: ``` Movie test = JsonConvert.DeserializeObject<Movie>(json); ``` I've tried to edit the `JsonProperty` on the `Movie` class to e.g. `cast.credits` but nothing works. I saw an answer to a similar question but I do not want to do this manually; I want it automatically. Json get underlying array without retrieving its member

Original source