解决方案比预期的要容易。您可以JsonConverter
使用GlobalConfiguration
. 我做了一个抽象包装器JsonConverter
,如下所示,其想法来自以下 SO 线程:如何在 JSON.NET 中实现自定义 JsonConverter 以反序列化基类对象列表?.
public abstract class CustomJsonConverter<T, TResult> : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Load token from stream
var token = JToken.Load(reader);
// Create target object based on token
var target = Create(objectType, token);
var targetType = target.GetType();
if (targetType.IsClass && targetType != typeof(string))
{
// Populate the object properties
var tokenReader = token.CreateReader();
CopySerializerSettings(serializer, tokenReader);
serializer.Populate(token.CreateReader(), target);
}
return target;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
T typedValued = (T)value;
TResult valueToSerialize = Convert(typedValued);
serializer.Serialize(writer, valueToSerialize);
}
public override bool CanConvert(Type objectType)
{
return typeof (T) == objectType;
}
protected virtual T Create(Type type, JObject jObject)
{
// reads the token as an object type
if (typeof(TResult).IsClass && typeof(T) != typeof(string))
{
return Convert(token.ToObject<TResult>());
}
var simpleValue = jObject.Value<TResult>();
return Convert(simpleValue);
}
protected abstract TResult Convert(T value);
protected abstract T Convert(TResult value);
private static void CopySerializerSettings(JsonSerializer serializer, JsonReader reader)
{
reader.Culture = serializer.Culture;
reader.DateFormatString = serializer.DateFormatString;
reader.DateTimeZoneHandling = serializer.DateTimeZoneHandling;
reader.DateParseHandling = serializer.DateParseHandling;
reader.FloatParseHandling = serializer.FloatParseHandling;
}
}
然后,您可以使用它来执行以下操作
public class DateTimeToStringJsonConverter : CustomJsonConverter<DateTime, string>
{
protected override string Convert(DateTime value)
{
return value.ToString();
}
protected override DateTime Convert(string value)
{
return DateTime.Parse(value);
}
}
GlobalConfiguration
然后最后在 Global.asax.cs 中注册一个实例
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new DateTimeToStringJsonConverter());
有什么想法/想法/意见吗?谢谢!
编辑:2018.10.16 - 更新代码以将值类型作为源类型处理并复制序列化程序设置,这要归功于原始SO 答案中的以下评论:
注意:这个解决方案遍布互联网,但有一个在极少数情况下会表现出来的缺陷。在 ReadJson 方法中创建的新 JsonReader 不会继承任何原始阅读器的配置值(Culture、DateParseHandling、DateTimeZoneHandling、FloatParseHandling 等)。在使用 serializer.Populate() 中的新 JsonReader 之前,应复制这些值。