【问题标题】:JSON deserialize to class with missing key in json [string could be a single string or list string]JSON反序列化为json中缺少键的类[字符串可以是单个字符串或列表字符串]
【发布时间】:2015-12-10 08:24:32
【问题描述】:

我有以下课程

    [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 可以是单个字符串或数组

那么我该如何反序列化呢。

它主要是抛出一个错误。

数组的反序列化不支持类

请指教 谢谢

【问题讨论】:

标签: c# json javascriptserializer


【解决方案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"]}

那么你的反序列化应该可以工作

【讨论】:

    【解决方案2】:

    您的问题是您的 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&lt;filters&gt;。

    因此:

            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。

    【讨论】:

      猜你喜欢
      • 2017-12-16
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多