C# 反序列化Json'时出现问题;使用System.Web.Script.Serialization.JavaScriptSerializer自定义转换器创建多维数组字段

C# 反序列化Json'时出现问题;使用System.Web.Script.Serialization.JavaScriptSerializer自定义转换器创建多维数组字段,c#,json,multidimensional-array,deserialization,javascriptserializer,C#,Json,Multidimensional Array,Deserialization,Javascriptserializer,嗨,我在反序列化json文件时遇到了一个问题,该文件可能具有不同的数据类型(float和float数组)。我从中得到一个使用自定义转换器的建议,它可以很好地用于一维数组。我目前得到了带有二维数组的JSON,而这个转换器无法处理相同的问题。下面是我的json的一个片段 { "name" : "foo", "value" : 457, "comment" : "bla bla bla", "data" : [ {

嗨,我在反序列化json文件时遇到了一个问题,该文件可能具有不同的数据类型(float和float数组)。我从中得到一个使用自定义转换器的建议,它可以很好地用于一维数组。我目前得到了带有二维数组的JSON,而这个转换器无法处理相同的问题。下面是我的json的一个片段

{
   "name"         : "foo",
   "value"      : 457,
   "comment"      : "bla bla bla",
   "data"   : [
      {        
         "name"       : "bar",
         "max"       : 200,
         "default"   : [
            [7,4],[2,2],[7,4],[1,1],[2,3],[3,1],[7,9]
         ]
      } 
   ]
}
其中,默认值有时可以是原始值,如

"default"   : 3.56
编辑:用于自定义序列化的代码

class RootObjectConverter : CustomPropertiesConverter<RootObject>
{
    const string ValuesName = "values";

    protected override IEnumerable<string> CustomProperties
    {
        get { return new[] { ValuesName }; }
    }

    protected override void DeserializeCustomProperties(Dictionary<string, object> customDictionary, RootObject obj, JavaScriptSerializer serializer)
    {
        object itemCost;
        if (customDictionary.TryGetValue(ValuesName, out itemCost) && itemCost != null)
            obj.Values = serializer.FromSingleOrArray<float>(itemCost).ToArray();
    }

    protected override void SerializeCustomProperties(RootObject obj, Dictionary<string, object> dict, JavaScriptSerializer serializer)
    {
        obj.Values.ToSingleOrArray(dict, ValuesName);
    }
}

public abstract class CustomPropertiesConverter<T> : JavaScriptConverter
{
    protected abstract IEnumerable<string> CustomProperties { get; }

    protected abstract void DeserializeCustomProperties(Dictionary<string, object> customDictionary, T obj, JavaScriptSerializer serializer);

    protected abstract void SerializeCustomProperties(T obj, Dictionary<string, object> dict, JavaScriptSerializer serializer);

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        // Detach custom properties
        var customDictionary = new Dictionary<string, object>();
        foreach (var key in CustomProperties)
        {
            object value;
            if (dictionary.TryRemoveInvariant(key, out value))
                customDictionary.Add(key, value);
        }

        // Deserialize and populate all members other than "values"
        var obj = new JavaScriptSerializer().ConvertToType<T>(dictionary);

        // Populate custom properties
        DeserializeCustomProperties(customDictionary, obj, serializer);

        return obj;
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        // Generate a default serialization.  Is there an easier way to do this?
        var defaultSerializer = new JavaScriptSerializer();
        var dict = defaultSerializer.Deserialize<Dictionary<string, object>>(defaultSerializer.Serialize(obj));

        // Remove default serializations of custom properties, if present
        foreach (var key in CustomProperties)
        {
            dict.RemoveInvariant(key);
        }

        // Add custom properties
        SerializeCustomProperties((T)obj, dict, serializer);

        return dict;
    }

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

public static class JavaScriptSerializerObjectExtensions
{
    public static void ReplaceInvariant<T>(this IDictionary<string, T> dictionary, string key, T value)
    {
        RemoveInvariant(dictionary, key);
        dictionary.Add(key, value);
    }

    public static bool TryRemoveInvariant<T>(this IDictionary<string, T> dictionary, string key, out T value)
    {
        if (dictionary == null)
            throw new ArgumentNullException();
        var keys = dictionary.Keys.Where(k => string.Equals(k, key, StringComparison.OrdinalIgnoreCase)).ToArray();
        if (keys.Length == 0)
        {
            value = default(T);
            return false;
        }
        else if (keys.Length == 1)
        {
            value = dictionary[keys[0]];
            dictionary.Remove(keys[0]);
            return true;
        }
        else
        {
            throw new ArgumentException(string.Format("Duplicate keys found: {0}", String.Join(",", keys)));
        }
    }

    public static void RemoveInvariant<T>(this IDictionary<string, T> dictionary, string key)
    {
        if (dictionary == null)
            throw new ArgumentNullException();
        foreach (var actualKey in dictionary.Keys.Where(k => string.Equals(k, key, StringComparison.OrdinalIgnoreCase)).ToArray())
            dictionary.Remove(actualKey);
    }

    public static void ToSingleOrArray<T>(this ICollection<T> list, IDictionary<string, object> dictionary, string key)
    {
        if (dictionary == null)
            throw new ArgumentNullException();
        if (list == null || list.Count == 0)
            dictionary.RemoveInvariant(key);
        else if (list.Count == 1)
            dictionary.ReplaceInvariant(key, list.First());
        else
            dictionary.ReplaceInvariant(key, list.ToArray());
    }

    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>();
    }
}
class RootObjectConverter:CustomPropertiesConverter
{
常量字符串值name=“values”;
受保护的重写IEnumerable CustomProperties
{
获取{returnnew[]{ValuesName};}
}
受保护的重写void反序列化CustomProperties(字典customDictionary、RootObject obj、JavaScriptSerializer序列化程序)
{
目标成本;
if(customDictionary.TryGetValue(ValuesName,out itemCost)&&itemCost!=null)
obj.Values=serializer.FromSingleOrray(itemCost.ToArray();
}
受保护的重写无效序列化CustomProperties(RootObject obj、Dictionary dict、JavaScriptSerializer序列化程序)
{
对象值到Singleorary(dict,ValuesName);
}
}
公共抽象类CustomPropertiesConverter:JavaScriptConverter
{
受保护的抽象IEnumerable CustomProperties{get;}
受保护的抽象void反序列化CustomProperties(Dictionary customDictionary、T obj、JavaScriptSerializer序列化程序);
受保护的抽象空序列化CustomProperties(T obj、Dictionary dict、JavaScriptSerializer序列化程序);
公共重写对象反序列化(IDictionary dictionary、类型、JavaScriptSerializer序列化程序)
{
//分离自定义属性
var customDictionary=newdictionary();
foreach(CustomProperties中的var键)
{
目标价值;
if(dictionary.TryRemoveInvariant(key,out值))
customDictionary.Add(键、值);
}
//反序列化并填充除“值”以外的所有成员
var obj=新的JavaScriptSerializer().ConvertToType(字典);
//填充自定义属性
反序列化CustomProperties(customDictionary、obj、序列化程序);
返回obj;
}
公共重写IDictionary序列化(对象obj、JavaScriptSerializer序列化程序)
{
//生成默认序列化。有更简单的方法吗?
var defaultSerializer=新的JavaScriptSerializer();
var dict=defaultSerializer.Deserialize(defaultSerializer.Serialize(obj));
//删除自定义属性的默认序列化(如果存在)
foreach(CustomProperties中的var键)
{
删除变量(键);
}
//添加自定义属性
序列化自定义属性((T)obj、dict、序列化器);
返回命令;
}
公共覆盖IEnumerable SupportedTypes
{
获取{returnnew[]{typeof(T)};}
}
}
公共静态类JavaScriptSerializerObjectExtensions
{
公共静态void ReplaceInvariant(此IDictionary字典、字符串键、T值)
{
删除变量(字典、键);
添加(键、值);
}
公共静态bool TryRemoveInvariant(此IDictionary字典、字符串键、out T值)
{
if(dictionary==null)
抛出新ArgumentNullException();
var keys=dictionary.keys.Where(k=>string.Equals(k,key,StringComparison.OrdinalIgnoreCase)).ToArray();
如果(keys.Length==0)
{
值=默认值(T);
返回false;
}
else if(keys.Length==1)
{
值=字典[键[0]];
删除(键[0]);
返回true;
}
其他的
{
抛出新的ArgumentException(string.Format(“找到重复的键:{0}”,string.Join(“,”,键));
}
}
公共静态void RemoveInvariant(此IDictionary字典,字符串键)
{
if(dictionary==null)
抛出新ArgumentNullException();
foreach(dictionary.Keys.Where(k=>string.Equals(k,key,StringComparison.OrdinalIgnoreCase)).ToArray())
删除字典(actualKey);
}
公共静态void到SingleOrarray(此ICollection列表、IDictionary字典、字符串键)
{
if(dictionary==null)
抛出新ArgumentNullException();
if(list==null | | list.Count==0)
字典。删除变量(键);
else if(list.Count==1)
dictionary.ReplaceInvariant(key,list.First());
其他的
dictionary.ReplaceInvariant(key,list.ToArray());
}
SingleOrArray的公共静态列表(此JavaScriptSerializer序列化程序,对象值)
{
如果(值==null)
返回null;
if(value.IsJsonArray())
{
返回值.AsJsonArray().Select(i=>serializer.ConvertToType(i)).ToList();
}
其他的
{
返回新列表{serializer.ConvertToType(value)};
}
}
公共静态bool IsJsonArray(此对象obj)
{
if(obj是string | | obj是IDictionary)
返回false;
返回对象是IEnumerable;
}
公共静态IEnumerable AsJsonArray(此对象对象obj)
{
return(对象为IEnumerable).Cast();
}
}
然后像这样使用它

var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new RootObjectConverter() });
var root = serializer.Deserialize<RootObject>(json);
var serializer=newJavaScriptSerializer();
serializer.RegisterConverters(新[]{new RootObjectConverter()});
var root=serializer.Deserialize(json);

有人能帮我解决这个问题吗?

我通过使用字典而不是类对象来解析不同的数据类型字段并使用键值访问相应的属性,解决了这个问题。谢谢大家的建议。

Cou