2016-08-24 3 views
0

Можно ли преобразовать список объектов из json в 2D-массив?Json.net C# конвертировать список объектов в 2D-массив

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 
     } 
    ] 
} 

Первый х и у являются размер 2D-массива. Можно ли использовать пользовательский JsonConverter для размещения информационного списка в этом массиве на основе x и y информационных объектов? Я знаю, что можно было бы преобразовать его сначала в список, а затем без Json.net в массив, но возможно ли это при десериализации?

+0

Возможный дубликат вопрос: HTTP: //stackoverflow.com/questions/39131705/need-to-conver tdeserialize-follow-json-in-c-sharp-object – GreatAndPowerfulOz

+0

Хакерный (но быстрый) способ сделать это - использовать регулярное выражение типа '" x ": (\ d +), \ s +" y ": (\ d +), ' –

+0

В вашем фрагменте JSON есть ошибка. – Aybe

ответ

1

Я создал пользовательский конвертер для вас:

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; } 
} 

Преобразователь:

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(); 
    } 
} 

Использование:

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); 
+0

Спасибо! Но лучше ли это (ram, cpu performance): удалить в классе предметов x и y. И замените цикл foreach на: 'for (int i = 0; i (); } 'И удалить список элементов :) Поскольку x и y« сохранены »в самом массиве. –

+0

1. Если вам нужна такая производительность - используйте другой сериализатор. 2. Было бы быстрее? Я не знаю. Добавьте таймер и проверьте его. 3. О дубликате x, y - Сделайте то, что хотите. Это просто пример, чтобы показать вам подход. –

0

Может быть, самый простой/быстрый способ сделать это вручную, как это:

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; } 
    } 
} 

Обратите внимание, что я не очень беспокоит, просто использовал интерфейс для скрытьx и y, не стесняйтесь дальнейшая настройка.

Кроме того, я использовал http://jsonclassgenerator.codeplex.com/ для преобразования в классы.

+0

Я пытался избежать преобразования в массив ПОСЛЕ десериализации. –

+0

Тогда ответ от @Amir Popovich может быть лучше для вас тогда :) – Aybe

Смежные вопросы