【发布时间】:2011-08-09 14:10:10
【问题描述】:
是否可以基于 JSON 对象的属性使用 JSON.NET 覆盖类型解析?基于现有的 API,我似乎需要一种接受 JsonPropertyCollection 并返回要创建的 Type 的方法。
注意:我知道TypeNameHandling attribute,但这增加了$type 属性。我无法控制源 JSON。
【问题讨论】:
是否可以基于 JSON 对象的属性使用 JSON.NET 覆盖类型解析?基于现有的 API,我似乎需要一种接受 JsonPropertyCollection 并返回要创建的 Type 的方法。
注意:我知道TypeNameHandling attribute,但这增加了$type 属性。我无法控制源 JSON。
【问题讨论】:
这似乎是通过创建自定义JsonConverter 并在反序列化之前将其添加到JsonSerializerSettings.Converters 来处理的。
nonplus 在 Codeplex 上的 JSON.NET discussions board 上留下了一个方便的示例。我已修改示例以返回自定义 Type 并遵循默认创建机制,而不是当场创建对象实例。
abstract class JsonCreationConverter<T> : JsonConverter
{
/// <summary>
/// Create an instance of objectType, based properties in the JSON object
/// </summary>
protected abstract Type GetType(Type objectType, JObject jObject);
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
Type targetType = GetType(objectType, jObject);
// TODO: Change this to the Json.Net-built-in way of creating instances
object target = Activator.CreateInstance(targetType);
serializer.Populate(jObject.CreateReader(), target);
return target;
}
}
这里是示例用法(也如上所述更新):
class VehicleConverter : JsonCreationConverter<Vehicle>
{
protected override Type GetType(Type objectType, JObject jObject)
{
var type = (string)jObject.Property("Type");
switch (type)
{
case "Car":
return typeof(Car);
case "Bike":
return typeof(Bike);
}
throw new ApplicationException(String.Format(
"The given vehicle type {0} is not supported!", type));
}
}
【讨论】:
WriteJson方法呢?