【问题标题】:How to override JavaScriptSerializer.Deserialize<T>()如何覆盖 JavaScriptSerializer.Deserialize<T>()
【发布时间】:2016-03-16 23:59:56
【问题描述】:

我得到一个数据一致性问题很少的 json 字符串。 例如 json 字符串中的一个字段返回一个字符串列表,而另一个 json 字符串中的相同字段返回一个字典(键、值对)。

我的类包含解析的 json 值,该字段的属性为 List。 因为这个数据一致性问题,json字符串解析不正确。

以下是我解析 json 字符串的代码

 JavaScriptSerializer serializer = new JavaScriptSerializer();
 myClass mc = serializer.Deserialize<myClass>(jsonString);

有什么方法可以编写自定义代码来解析 json 字符串并将其映射到 myClass?

【问题讨论】:

标签: c# json javascriptserializer


【解决方案1】:

你没有给出你想要完成的具体例子,这意味着我们需要自己制作一个例子。考虑以下类:

public class myClass
{
    public Dictionary<string, string> data { get; set; }
}

并考虑以下两个 JSON 字符串:

{"data": ["zero", 1, "two"]}
{"data": {"0": "zero", "1":1, "2":"two"}}

看起来您可能希望以相同的方式解析这些,将数组转换为 Dictionary&lt;string, string&gt;,其键是数组索引。这可以通过以下JavaScriptConverter 来完成:

public class myClassConverter : JavaScriptConverter
{
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        var myClass = new myClass();

        object data;
        if (dictionary.TryGetValue("data", out data))
        {
            if (data.IsJsonArray())
            {
                myClass.data = data.AsJsonArray()
                    .Select((o, i) => new KeyValuePair<int, object>(i, o))
                    .ToDictionary(p => p.Key.ToString(NumberFormatInfo.InvariantInfo), p => serializer.ConvertToType<string>(p.Value));
            }
            else if (data.IsJsonObject())
            {
                myClass.data = data.AsJsonObject()
                    .ToDictionary(p => p.Key, p => serializer.ConvertToType<string>(p.Value));
            }
        }

        return myClass;
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }

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

public static class JavaScriptSerializerObjectExtensions
{
    public static bool IsJsonArray(this object obj)
    {
        if (obj is string || obj.IsJsonObject())
            return false;
        return obj is IEnumerable;
    }

    public static IEnumerable<object> AsJsonArray(this object obj)
    {
        return (obj as IEnumerable).Cast<object>();
    }

    public static bool IsJsonObject(this object obj)
    {
        return obj is IDictionary<string, object>;
    }

    public static IDictionary<string, object> AsJsonObject(this object obj)
    {
        return obj as IDictionary<string, object>;
    }
}

传递给Deserialize()IDictionary&lt;string, object&gt; 对应于正在转换的JSON 对象中的键/值对。对于特定键(在本例中为 "data"),如果值是 JSON 对象,则 object 值将是 IDictionary&lt;string, object&gt;,如果值是 IEnumerable(特别是 ArrayList)是一个 JSON 数组。通过根据适当的类型测试值,可以进行转换。

转换器只进行反序列化。像这样使用它:

        var jsonString1 = @"{""data"": [""zero"", 1, ""two""]}";
        var jsonString2 = @"{""data"": {""0"": ""zero"", ""1"":1, ""2"":""two""}}";

        var deserializer = new JavaScriptSerializer();
        deserializer.RegisterConverters(new JavaScriptConverter[] { new myClassConverter() });

        var newJson1 = new JavaScriptSerializer().Serialize(deserializer.Deserialize<myClass>(jsonString1));
        var newJson2 = new JavaScriptSerializer().Serialize(deserializer.Deserialize<myClass>(jsonString2));

        Console.WriteLine(newJson1); // Prints {"data":{"0":"zero","1":"1","2":"two"}}
        Console.WriteLine(newJson2); // Prints {"data":{"0":"zero","1":"1","2":"two"}}

        Debug.Assert(newJson1 == newJson2); // No assert

【讨论】:

    猜你喜欢
    • 2012-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多