I have below class
[Serializable]
public class filters
{
public List<string> key1 { get; set; }
public List<string> key2 { get; set; }
public List<string> key3 { get; set; }
}
and json string is
[{"key1": "key1value"}]
deserializing like
filters objFilter = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<filters>(json);
json string may contain key1, key2 and key3 or may not.
key1, key2, key3 may be a single string or array
So how can i deserialize it.
It is throwing an error mostly.
class is not supported for deserialization of an array
Please advise
Thanks
The problem with your code is your json is incorrect
Take the following code in a console app and see what you get
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);
Or change your json just to the following
The '[]' in your json is a represenation that it it is an array, so you are trying to deserialize an array to type filters
{"key1":["key1value"]}
then your deserialize should work
Your problem is that your JSON has properties whose values can either be strings or arrays of strings, like so:
{
"key1": "key1value",
"key2": [
"key2value1",
"key2value2"
]
}
To parse this you have chosen to use JavaScriptSerializer
which is a very simple reflection-based serializer. Its ability to customize the mapping between objects and JSON is limited. Nevertheless you can write a JavaScriptConverter
for your filters
class that tests to see whether values of the "keyX"
properties are single items or arrays, and deserialize appropriately:
[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>();
}
}
Also, your root JSON container is an array rather than a object (i.e. the outer delimiters are []
not {}
), so you need to deserialize it as a List<filters>
.
Thus:
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);
This outputs [{"key1":"key1value","key2":"key2value","key3":["key3value1","key3value2"]}]
as desired.
Another option would be to switch to Json.NET, which has much more flexible tools for mapping objects to JSON. See How to handle both a single item and an array for the same property using JSON.net for specific instructions.