c#中的自定义JavaScript解串器#
我正在研究一个与浏览器集成的C#应用程序。 浏览器将以json格式向C#发送一些数据。c#中的自定义JavaScript解串器#
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。
谢谢。
这里的难点在于JavaScriptConverter
允许你将一个JSON对象映射到一个c#类 - 但在你的JSON中,"xyz"
只是一个字符串,而不是一个对象。因此,您无法为someOtherDataType
指定转换器,而是必须为包含someOtherDataType
实例的每个类指定转换器。
(请注意,在Json.NET定制转换器的功能没有此限制。如果你愿意切换到库,你可以写一个JsonConverter
转换的someOtherDataType
所有用途从和JSON字符串。)
写这样的JavaScriptConverter
:
- 覆盖
JavaScriptConverter.Deserialize
- 创建第二
Dictionary<string, Object>
滤除需要定制转换的字段。 - 请致电
new JavaScriptSerializer.ConvertToType<T>
从过滤的字典中反序列化标准字段。 - 手动转换剩余的字段。
- 重写
SupportedTypes
以返回容器类型。
因此,在你的榜样,你可以这样做:
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
}
}
感谢dbc,它对我的应用程序使用此解决方案工作良好。 – Anurag
是什么让这两个对象有什么不同?如何在反序列化之前将它们分开?你有没有反序列化的C#类(如果有的话,你可以发布它)吗? – br4d
是的,我确实有一堂课,就像dbc的答案一样。 – Anurag