2013-08-16 2 views
0

Моя строка JSONКак сделать String.Join при десериализации строки JSON?

{ 
    "account_id": "123456", 
    "capabilities": [ 
     2, 
     6, 
     15, 
     11 
    ], 
    "currency": "USD" 
} 

Мое определение класса

public class AdAccount 
{ 
    public long account_id { get; set; } 
    public string currency { get; set; } 
    public List<int> capabilities { get; set; } 
} 

код Desearialization:

var account = JsonConvert.DeserializeObject<Account>(data, new JsonSerializerSettings() { MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore }); 

Это все работает отлично. Однако я хочу, чтобы «возможности» были разделены запятыми, например «2,6,15,11». Так что я попытался

public class AdAccount 
{ 
    public long account_id { get; set; } 
    public string currency { get; set; } 
    private string _capabilities; 
    public string capabilities { get { return _capabilities; } set { _capabilities = String.Join(",", value); } } 
} 

Но это бросает исключение

Ошибка чтения строки. Неожиданный токен: StartArray. Путь «возможности», строка 1, позиция 544.

Можно ли делать то, что я хочу, во время десериализации?

Спасибо.

+0

@ rjv_mjn Вы пробовали 'public String возможности {get; задавать; } 'вместо' public List возможностей {get; задавать; } ' – kbvishnu

+2

Зачем вам нужно, чтобы ваше представление в памяти было труднее работать? Разумеется, было бы лучше преобразовать список в ваше * более приятное представление ('Account') только тогда, когда вам нужно. –

+0

@JonSkeet Моя цель в коде, который я пишу, это получить строку JSON и поместить ее в дБ, где мы немного обрабатываем данные. Значение «возможностей» не имеет для нас большого значения, но нам не хотелось бы, чтобы код удалял любые данные, которые мы получаем. JSON -> Deserialized Obj -> DB. Благодарю. – Justin

ответ

0

Я предлагаю вам два представления:

  • "Естественный" представление, которое имеет List<int>
  • В "базе данных" представление, которое соединяемых string

Вы можете легко записывать преобразователи от одного к другому, а это означает, что вам не нужно делать ничего особенного в самих сериализационных/десериализационных путях , Стоимость состоит в том, что вы, конечно, получаете две модели. Я бы рекомендовал, чтобы подавляющее большинство вашего кода использовало «естественное» представление - используйте только представление БД в качестве шага, когда вы имеете дело с базой данных.

+0

Я выбрал этот ответ, поскольку это заставило меня не писать собственный код для одного конкретного экземпляра, а также иметь больше смысла (хотя, как упоминалось, немного избыточности). Благодарю. – Justin

2

Я предлагаю вам создать дополнительное свойство для хранения отображаемого значения (вашего CSV). Это свойство будет доступно только для чтения и будет обновлять/пересчитывать себя при обновлении списка.

Я не уверен, что вам нужно добавить игнорирование парсера Json, чтобы игнорировать свойство.

Преимущество этого подхода заключается в том, что значение рассчитывается только при доступе к значению.

+0

'Преимущество этого подхода заключается в том, что значение вычисляется только при доступе к значению.' И каждый раз, когда вы получаете доступ к значению. – I4V

+0

@ I4V, да, он будет рассчитан на доступ к каждому пользователю. Для чего-то тривиального, это было бы нормально. Но я могу понять, что для более крупных систем вы, возможно, захотите взглянуть на ленивую загрузку. – gunr2171

+0

@ gunr2171 спасибо. Если все не удается, я могу закончить работу только для чтения. Поскольку он доступен только один раз, производительность не должна быть такой плохой. Кроме того, массив int составляет не более 5-10 элементов. – Justin

2

Вы можете создать собственный конвертер который может сделать неявное преобразование из List<int> в строку

var obj = JsonConvert.DeserializeObject<AdAccount>(json,new MyConverter()); 

.

public class MyConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(string); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (objectType == typeof(string) && reader.TokenType == JsonToken.StartArray) 
     { 
      List<long> nums = new List<long>(); 
      reader.Read(); 
      while (reader.TokenType != JsonToken.EndArray) 
      { 
       nums.Add((long)reader.Value); 
       reader.Read(); 
      } 
      return String.Join(",", nums); 
     } 
     return existingValue; 
    } 

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

public class AdAccount 
{ 
    public long account_id { get; set; } 
    public string currency { get; set; } 
    public string capabilities { get;set; } 
} 
+0

Он хочет, чтобы все было наоборот (список был разобран как строка с разделителями-запятыми). –

+0

@SimonBelanger Я обновил ответ, он работает в обоих направлениях .... – I4V

+0

Я имею в виду, что json coming in - это список. Вместо этого десериализатор возьмет строку. :) –

0

Имейте дополнительное свойство, которое анализирует версию вашего List<int> Свойство и устанавливает его внутри сеттера List<int>.

public class AdAccount 
{ 
    public long account_id { get; set; } 
    public string currency { get; set; } 
    private List<int> _capabilities; 
    public List<int> capabilities 
    { 
     get { return _capabilities; } 
     set { _capabilities = value; this.ParsedCapabilities = string.Join(",", value); } 
    } 
    public string ParsedCapabilities { get; set; } 
} 
Смежные вопросы