c#中的自定义javascript反序列化器

时间:2015-04-22 17:38:02

标签: c# json serialization javascriptserializer

我正在开发一个集成了浏览器的C#应用​​程序。 浏览器将以json格式向C#发送一些数据。

json中的一些字段可以使用javascript反序列化来反序列化,但我有一些数据需要自定义反序列化器,我需要注册一个反序列化器,但事情是必须为那些调用自定义反序列化器必须为其他数据调用特殊数据和默认的javascript反序列化器,可以从C#中的目标字段的数据类型/名称中识别特殊数据。我怎样才能做到这一点。

像这样的东西。

public class example
{
  public string abc;
  public someOtherDataType xyz;

  public void example()
  {
    serializer = new JavaScriptSerializer();

    // receive json string

        serializer.RegisterConverters(new JavaScriptConverter[]
         { 
    new System.Web.Script.Serialization.CS.CustomConverter() 
    });

    //call deserializer

}
}

json字符串将类似于

{
"abc" : "valueabc"
"xyz" : "valueXYZ"
}

现在必须仅在反序列化xyz期间调用自定义反序列化器,并且必须为abc调用default。

谢谢。

1 个答案:

答案 0 :(得分:2)

这里的难点在于JavaScriptConverter允许您将JSON对象映射到c#类 - 但在JSON中,"xyz"只是一个字符串,而不是一个对象。因此,您无法为someOtherDataType指定转换器,而是必须为包含someOtherDataType实例的每个类指定转换器。

(请注意,Json.NET中的自定义转换器功能没有此限制。如果您愿意切换到该库,则可以编写JsonConverter来转换someOtherDataType的所有用途以及JSON字符串。)

写下这样的JavaScriptConverter

  1. 覆盖JavaScriptConverter.Deserialize
  2. 创建第二个Dictionary<string, Object>过滤掉需要自定义转化的字段。
  3. 调用new JavaScriptSerializer.ConvertToType<T>从过滤后的字典中反序列化标准字段。
  4. 手动转换剩余的字段。
  5. 覆盖SupportedTypes以返回容器类型。
  6. 因此,在您的示例中,您可以执行以下操作:

    public class example
    {
        public string abc;
        public someOtherDataType xyz;
    }
    
    // Example implementation only.
    public class someOtherDataType
    {
        public string SomeProperty { get; set; }
    
        public static someOtherDataType CreateFromJsonObject(object xyzValue)
        {
            if (xyzValue is string)
            {
                return new someOtherDataType { SomeProperty = (string)xyzValue };
            }
            return null;
        }
    }
    
    class exampleConverter : JavaScriptConverter
    {
        public override IEnumerable<Type> SupportedTypes
        {
            get { return new[] { typeof(example) }; }
        }
    
        // Custom conversion code below
    
        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            var defaultDict = dictionary.Where(pair => pair.Key != "xyz").ToDictionary(pair => pair.Key, pair => pair.Value);
            var overrideDict = dictionary.Where(pair => !(pair.Key != "xyz")).ToDictionary(pair => pair.Key, pair => pair.Value);
    
            // Use a "fresh" JavaScriptSerializer here to avoid infinite recursion.
            var value = (example)new JavaScriptSerializer().ConvertToType<example>(defaultDict);
    
            object xyzValue;
            if (overrideDict.TryGetValue("xyz", out xyzValue))
            {
                value.xyz = someOtherDataType.CreateFromJsonObject(xyzValue);
            }
            return value;
        }
    
        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    

    然后,测试:

    public class TestClass
    {
        public static void Test()
        {
            // receive json string
            string json = @"{
    ""abc"" : ""valueabc"",
    ""xyz"" : ""valueXYZ""
    }";
            var serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new JavaScriptConverter[]
             { 
                 new exampleConverter()
             });
    
            var example = serializer.Deserialize<example>(json);
            Debug.Assert(example.abc == "valueabc" && example.xyz.SomeProperty == "valueXYZ"); // No assert
        }
    }