JSON反序列化为类,json中缺少键[string可以是单个字符串或列表字符串]

时间:2015-12-10 08:24:32

标签: c# json javascriptserializer

我有以下课程

    [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字符串可能包含key1,key2和key3,也可能不包含。

key1,key2,key3可以是单个字符串或数组

那我怎样才能反序化呢。

主要是犯了错误。

  数组的反序列化不支持

请指教 感谢

2 个答案:

答案 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中的'[]'表示它是一个数组,所以你试图反序列化一个数组来输入过滤器

{"key1":["key1value"]}

那么你的反序列化应该可行

答案 1 :(得分:0)

您的问题是您的JSON具有其值可以是字符串或字符串数​​组的属性,如下所示:

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

要解析此问题,您已选择使用JavaScriptSerializer这是一个非常简单的基于反射的序列化程序。它能够自定义对象和JSON之间的映射是有限的。不过,您可以为filters类编写JavaScriptConverter,以测试"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