2015-12-10 3 views
3

У меня есть ниже классаJSON Deserialize в класс с отсутствующим ключом в JSON [строка может быть одной строкой или список строками]

[Serializable] 
    public class filters 
    { 
     public List<string> key1 { get; set; } 
     public List<string> key2 { get; set; } 
     public List<string> key3 { get; set; } 
    } 

и JSON строка

[{"key1": "key1value"}] 

десериализация как

filters objFilter = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<filters>(json); 

строка json может содержать ключ1, key2 и key3 или может не отображаться.

key1, key2, ключ3 может быть одна строка или массив

Итак, как я десериализации его.

В основном это ошибка.

класс не поддерживается для десериализации массива

Пожалуйста посоветуйте Благодаря

+4

Для начала используйте JSON.NET (Newtonsoft.json) –

+1

Почему вы указали, что key1, key2 и key3 являются List , когда предоставленный вами JSON содержит одно значение? Если это был список, JSON должен сказать '{" key1 ": [" Keyval "]}'. – GeirGrusom

+0

Это может быть одна строка или список –

ответ

1

Проблемы с кодом вашего JSON неверен

Возьмет следующий код в консоли приложение и посмотреть, что вы получаете

var filtr = new filters { key1 = new List<string>() { "key1value" } }; 
var json = new JavaScriptSerializer().Serialize(filtr); 
var text = "{\"key1\":[\"key1value\"]}"; 
filtr = new JavaScriptSerializer().Deserialize<filters>(text); 

Или изменить JSON только к следующему

«[]» в вашем JSON является represenation, что это массив, так что вы пытаетесь десериализации массив типа фильтров

{"key1":["key1value"]} 

то ваш Deserialize должен работать

0

Ваша проблема заключается в том, что ваш JSON имеет свойства, значения которых могут быть либо строки или массивы строк, например:

{ 
    "key1": "key1value", 
    "key2": [ 
     "key2value1", 
     "key2value2" 
    ] 
} 

Чтобы разобрать это, вы выбрали JavaScriptSerializer, который представляет собой очень простой сериализатор на основе отражения. Его способность настраивать отображение между объектами и JSON ограничена. Тем не менее вы можете написать JavaScriptConverter для filters класса, который проверяет, чтобы увидеть значения "keyX" свойств, являются ли отдельные элементы или массивы, и десериализации соответственно:

[Serializable] 
public class filters 
{ 
    public List<string> key1 { get; set; } 
    public List<string> key2 { get; set; } 
    public List<string> key3 { get; set; } 
} 

class filtersConverter : JavaScriptConverter 
{ 
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
    { 
     var filters = new filters(); 
     filters.key1 = serializer.FromSingleOrArray<string>(dictionary, "key1"); 
     filters.key2 = serializer.FromSingleOrArray<string>(dictionary, "key2"); 
     filters.key3 = serializer.FromSingleOrArray<string>(dictionary, "key3"); 
     return filters; 
    } 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) 
    { 
     if (obj == null) 
      return null; 
     var filters = (filters)obj; 
     var dictionary = new Dictionary<string, object>(); 
     filters.key1.ToSingleOrArray(dictionary, "key1"); 
     filters.key2.ToSingleOrArray(dictionary, "key2"); 
     filters.key3.ToSingleOrArray(dictionary, "key3"); 
     return dictionary; 
    } 

    public override IEnumerable<Type> SupportedTypes 
    { 
     get { return new[] { typeof(filters) }; } 
    } 
} 

public static class JavaScriptSerializerObjectExtensions 
{ 
    public static void ToSingleOrArray<T>(this ICollection<T> list, IDictionary<string, object> dictionary, string key) 
    { 
     if (list == null || list.Count == 0) 
      return; 
     if (list.Count == 1) 
      dictionary.Add(key, list.First()); 
     else 
      dictionary.Add(key, list); 
    } 

    public static List<T> FromSingleOrArray<T>(this JavaScriptSerializer serializer, IDictionary<string, object> dictionary, string key) 
    { 
     object value; 
     if (!dictionary.TryGetValue(key, out value)) 
      return null; 
     return serializer.FromSingleOrArray<T>(value); 
    } 

    public static List<T> FromSingleOrArray<T>(this JavaScriptSerializer serializer, object value) 
    { 
     if (value == null) 
      return null; 
     if (value.IsJsonArray()) 
     { 
      return value.AsJsonArray().Select(i => serializer.ConvertToType<T>(i)).ToList(); 
     } 
     else 
     { 
      return new List<T> { serializer.ConvertToType<T>(value) }; 
     } 
    } 

    public static bool IsJsonArray(this object obj) 
    { 
     if (obj is string || obj is IDictionary) 
      return false; 
     return obj is IEnumerable; 
    } 

    public static IEnumerable<object> AsJsonArray(this object obj) 
    { 
     return (obj as IEnumerable).Cast<object>(); 
    } 
} 

Кроме того, корневая JSON контейнер представляет собой массив, а не объект (т.е. внешние разделители [] не {}), поэтому вам необходимо десериализовать его как List<filters>.

Таким образом:

 var json = @"[{""key1"": ""key1value"", ""key2"": [""key2value""],""key3"": [""key3value1"", ""key3value2""]}]"; 

     var serializer = new JavaScriptSerializer(); 
     serializer.RegisterConverters(new JavaScriptConverter[] { new filtersConverter() }); 

     var filters = serializer.Deserialize<List<filters>>(json); 

     var newJson = serializer.Serialize(filters); 

     Console.WriteLine(newJson); 

Это выводит [{"key1":"key1value","key2":"key2value","key3":["key3value1","key3value2"]}] по желанию.

Другим вариантом было бы перейти на Json.NET, которая имеет гораздо более гибкие инструменты для сопоставления объектов с JSON. См. How to handle both a single item and an array for the same property using JSON.net для получения конкретных инструкций.