Iceflower S
Iceflower S

Reputation: 194

Json.net c# convert list of objects into a 2D array

Is it possible to convert a list of objects from json to an 2D array?

Data.json

{
    "x": 6,
    "y": 6,
    "information": [
        {
            "x": 0,
            "y": 0,
            "info": "First item",
            "info2": 1
        },
        {
            "x": 1,
            "y": 3,
            "info": "Second item",
            "info2": 3
        },
        {
            "x": 3,
            "y": 4,
            "info": "Third item",
            "info2": 2
        }
    ]
}

The first x and y are the size of the 2D array. Is it possible to use the Custom JsonConverter to put the information list into this array based on the x and y of the info objects? I know that it could be possible to convert it first into a list and then without Json.net into an array, but would it be possible while deseriliazing?

Upvotes: 0

Views: 748

Answers (2)

Amir Popovich
Amir Popovich

Reputation: 29836

I've created a custom converter for you:

Poco:

public class Item
{
    [JsonProperty("x")]
    public int X { get; set; }

    [JsonProperty("y")]
    public int Y { get; set; }

    [JsonProperty("info")]
    public string Info { get; set; }

    [JsonProperty("info2")]
    public string Info2 { get; set; }
}

Converter:

public class ItemJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Item[,]);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jObject = JObject.Load(reader);

        var x = jObject.Value<int>("x");
        var y = jObject.Value<int>("y");

        var items = jObject.GetValue("information").ToObject<IEnumerable<Item>>();
        var itemsArray = new Item[x, y];

        foreach (var item in items)
        {
            itemsArray[item.X, item.Y] = item;
        }

        return itemsArray;
    }

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

Usage:

var jsonStr = @"{
                    ""x"": 3,
                    ""y"": 1,
                    ""information"": [
                        {
                            ""x"": 0,
                            ""y"": 0,
                            ""info"": ""First item"",
                            ""info2"": 1
                        },
                        {
                            ""x"": 1,
                            ""y"": 0,
                            ""info"": ""Second item"",
                            ""info2"": 3
                        },
                        {
                            ""x"": 2,
                            ""y"": 0,
                            ""info"": ""Third item"",
                            ""info2"": 2
                        }
                    ]
                }";

var jss = new JsonSerializerSettings();
jss.Converters.Add(new ItemJsonConverter());
var obj = JsonConvert.DeserializeObject<Item[,]>(jsonStr, jss);

Upvotes: 1

aybe
aybe

Reputation: 16672

Maybe the simplest/fastest way is to do it manually, like this:

using Newtonsoft.Json;

namespace WpfApplication3
{
    public partial class MainWindow
    {
        private readonly string json = @"
{
    ""x"": 6,
    ""y"": 6,
    ""information"": [
        {
            ""x"": 0,
            ""y"": 0,
            ""info"": ""First item"",
            ""info2"": 1
        },
        {
            ""x"": 1,
            ""y"": 3,
            ""info"": ""Second item"",
            ""info2"": 3
        },
        {
            ""x"": 3,
            ""y"": 4,
            ""info"": ""Third item"",
            ""info2"": 2
        }
    ]
}";

        public MainWindow()
        {
            InitializeComponent();

            var o = JsonConvert.DeserializeObject<SampleResponse1>(json);
            var array = new IInformation[o.X, o.Y];
            foreach (var i in o.Information)
            {
                array[i.X, i.Y] = i;
            }
        }
    }

    internal class SampleResponse1
    {
        [JsonProperty("x")]
        public int X { get; set; }

        [JsonProperty("y")]
        public int Y { get; set; }

        [JsonProperty("information")]
        public Information[] Information { get; set; }
    }

    internal class Information : IInformation
    {
        [JsonProperty("x")]
        public int X { get; set; }

        [JsonProperty("y")]
        public int Y { get; set; }

        #region IInformation Members

        [JsonProperty("info")]
        public string Info { get; set; }

        [JsonProperty("info2")]
        public int Info2 { get; set; }

        #endregion
    }

    internal interface IInformation
    {
        string Info { get; set; }
        int Info2 { get; set; }
    }
}

Note that I didn't really bother, just used an interface to hide x and y, feel free to further tune it.

Also, I used http://jsonclassgenerator.codeplex.com/ to convert to classes.

Upvotes: 0

Related Questions