Ваша проблема заключается в том, что ваш 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 для получения конкретных инструкций.
Для начала используйте JSON.NET (Newtonsoft.json) –
Почему вы указали, что key1, key2 и key3 являются List, когда предоставленный вами JSON содержит одно значение? Если это был список, JSON должен сказать '{" key1 ": [" Keyval "]}'. –
GeirGrusom
Это может быть одна строка или список –