Json.NET: deserialize nested arrays into strongly typed object

deserialization, json, json.net, multidimensional-array

Solution

I finally figured out how to do this. I was needed to use `serializer.Deserialize` inside of `JsonConverter`. So, here is a working example.

class Program
{
    static string json = @"{
                                ""files"":
                                [
                                    ""hash string"",
                                    [
                                        [""first file name"", 12],
                                        [""second file name"", 34]
                                    ]
                                ]
                            }";

    static void Main(string[] args)
    {
        RootObject container = JsonConvert.DeserializeObject<RootObject>(json);
    }
}

public class RootObject
{
    [JsonProperty("files")]
    public FilesContainer Container
    {
        get;
        set;
    }
}

[JsonConverter(typeof(FilesContainerJsonConverter))]
public class FilesContainer
{
    public string Hash
    {
        get;
        set;
    }

    public File[] Files
    {
        get;
        set;
    }
}

public class FilesContainerJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        FilesContainer obj = new FilesContainer();
        obj.Hash = reader.ReadAsString();
        reader.Read(); // to StartArray
        obj.Files = serializer.Deserialize<File[]>(reader);
        reader.Read(); // to EndArray

        return obj;
    }

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

[JsonConverter(typeof(FileJsonConverter))]
public class File
{
    public string Name
    {
        get;
        set;
    }

    public int Size
    {
        get;
        set;
    }
}

class FileJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        File obj = new File
        {
            Name = reader.ReadAsString(),
            Size = reader.ReadAsInt32().GetValueOrDefault()
        };

        reader.Read(); // to EndArray

        return obj;
    }

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

Problem

I'm writing client application, which should process server responses. Responses are in JSON. I decided to use Json.NET to deserialize them. And I couldn't simplify or modify those responses (on server side). Particular difficulties of this specific JSON response is that different object types is in same array: hash and array of files. So, I would like to deserialize this array straight ahead into strongly typed object, rather than array of objects. I think that it should be possible to achieve with `CustomCreationConverter`, but I couldn't figure how. JSON: ``` { "files": [ "hash string", [ ["first file name", 12], ["second file name", 34] ] ] } ``` Object structure, which I'm trying to achieve: ``` public class RootObject { [JsonProperty("files")] public FilesContainer Container { get; set; } } public class FilesContainer { public string Hash { get; set; } public File[] Files { get; set; } } [JsonConverter(typeof(FileJsonConverter))] public class File { public string Name { get; set; } public int Size { get; set; } } class FileJsonConverter : JsonConverter { public override bool CanConvert(Type objectType) { throw new NotImplementedException(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { File obj = new File { Name = reader.ReadAsString(), Size = reader.ReadAsInt32().GetValueOrDefault() }; reader.Read(); return obj; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } ```

Original source