2015-04-10 2 views
1

Хорошо, поэтому я работаю над созданием REST-API, и для того, чтобы засеять мою базу данных, я использую существующие данные в формах огромных JSON-файлов. И у меня есть проблема, когда дело доходит до десериализации одного из полей.Deserialize string-array, содержащий другой массив

Так JSON выглядит следующим образом:

{ 
    "name" : "Magic 2013", 
    "booster" : [ 
    "land", 
    "marketing", 
    "common", 
    "common", 
    "common", 
    "common", 
    "common", 
    "common", 
    "common", 
    "common", 
    "common", 
    "common", 
    "uncommon", 
    "uncommon", 
    "uncommon", 
    [ 
     "rare", 
     "mythic rare" 
    ] 
    ] 
} 

И когда вы смотрите на это, вероятно, можно определить проблему. Есть поле под названием booster, которое представляет собой массив строк. Но последний элемент не является строкой. Это еще один массив. Поэтому, пытаясь десериализовать его на строку [], поле перестает работать.

Мне нужно работать с этим форматом - для меня нет возможности изменить его, поэтому мне придется найти разумный способ решить эту проблему. Это то, с чем мне нужна помощь.

Есть ли какой-либо способ с JSON.NET, который я мог бы фактически десериализовать это? Как-то я мог сделать какое-то ручное сопоставление, говоря, что всякий раз, когда я достигаю внутреннего массива, я собираюсь сделать какой-то пользовательский код?

Я был бы признателен за любую помощь!

Спасибо!

ответ

3

Вы могли бы определить booster собственность как JArray:

public JArray Booster { get; set; } 

Это не навязывает определенный тип данных массива. Вы можете затем цикл по каждому элементу этого массива (который будет JToken) и испытания, если это значение строки или еще один JArray и действовать соответственно:

foreach (JToken token in model.Booster) 
{ 
    var array = token as JArray(); 
    if (array != null) 
    { 
     // The element is an array, so you can process its subelements here 
    } 
    else 
    { 
     // It's probably a string element 
     string value = token.ToObject<string>(); 
    } 
} 
+1

Это было именно то, что я искал. Я не знал, что JArray можно использовать так. Но это, наверное, то, за что это _активно. Так что спасибо! Я сделаю это :) Приятного дня. – Ajaco

0

Если он всегда будет последним элементом, который будет есть массив вместо строки, вы можете десериализатор использует

public class RootObject 
{ 
    public string name { get; set; } 
    public List<object> booster { get; set; } 
} 

, а затем извлечь элемент booster списка с помощью

var oddItem = booster[booster.Count -1]; 

Это при условии, что его всегда последний элемент, который представляет собой массив

0

Так что это работает для меня:

class WhateverMyThingIsNamed 
{ 
    public string Name { get; set; } 

    public object[] Booster { get; set; } 

    public IEnumerable<string> GetBooster() 
    { 
     foreach (var o in Booster) 
     { 
      if (o is string) 
      { 
       yield return (string) o; 
      } 
      else if (o is JArray) 
      { 
       foreach (var element in (JArray) o) 
       { 
        yield return element.Value<string>(); 
       } 
      } 
      else 
      { 
       throw new InvalidOperationException("Unexpected element"); 
      } 
     } 
    } 
} 

... 

var json = File.ReadAllText("json1.json"); 
var data = new JsonSerializer().Deserialize<WhateverMyThingIsNamed>(new JsonTextReader(new StringReader(json))); 
var boosterList = data.GetBooster().ToList();