0

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?

4
  • Possible duplicate question: stackoverflow.com/questions/39131705/… Commented Aug 24, 2016 at 21:19
  • A hacky (but fast) way to do it is to use a regular expression like "x": (\d+),\s+"y": (\d+), Commented Aug 24, 2016 at 21:20
  • There's an error in your JSON fragment. Commented Aug 24, 2016 at 21:26
  • i fixed it. Thanks. Commented Aug 24, 2016 at 21:28

2 Answers 2

1

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);
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks!! But would it better (ram, cpu performance): to remove in item class x and y. And replace the foreach loop with: for (int i = 0; i < jObject["information"].Count(); i++) { itemsArray[(int) jObject["information"][i]["x"], (int) jObject["information"][i]["y"]] = jObject["information"][i].ToObject<Item>(); } And remove the items list :) Since the x and y is "stored" in the array itself.
1. If you need that kind of performance - Use a different serializer. 2. Would it be faster? I don't know. Add a timer and check it out. 3. About the duplicate x,y - Do what you want. This is just an example to show you the approach.
0

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.

2 Comments

I was trying to avoid the converting to an array AFTER the deserialization.
Then the answer from @Amir Popovich might be better for you then :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.