在小提琴上测试:https://dotnetfiddle.net/RyxMjm
using NewtonSoft.Json;
让SomeClass
是需要自定义json转换器的库类。它附带的库提供了自定义json转换器UsualConverter
,并通过在类定义中使用JsonConverter
属性来指定该转换器,从而将该转换器链接到该类。
[JsonConverter(typeof(UsualConverter))]
class SomeClass {
public int A;
}
class UsualConverter : JsonConverter {
public override bool CanConvert(Type objectType)
=> objectType == typeof(SomeClass);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var jObject = JObject.ReadFrom(reader);
return new SomeClass {
A = jObject["A"].ToObject<int>(),
};
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
var jObject = new JObject();
jObject["A"] = ((SomeClass)value).A;
jObject.WriteTo(writer);
}
}
但是我现在需要实现和使用一个不同的json转换器。所以我创建了自己的:
class SpecialConverter : JsonConverter {
public override bool CanConvert(Type objectType)
=> objectType == typeof(SomeClass);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var jObject = JObject.ReadFrom(reader);
return new SomeClass {
A = 100,
};
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
var jObject = new JObject();
jObject["A"] = "SpecialValue";
jObject.WriteTo(writer);
}
}
当我根本无法让JsonConvert使用我的新转换器时,就会出现问题……它总是使用在类定义中使用属性指定的原始标头。
以下代码引发异常。如何使用新的自定义转换器完成序列化/反序列化工作?
class Program {
static void Main(string[] args) {
var settings = new JsonSerializerSettings();
settings.Converters.Add(new SpecialConverter());
var json = JsonConvert.SerializeObject(new SomeClass { A = 10 }, settings);
if (!json.Contains("SpecialValue"))
throw new Exception("Wrong converter was used.");
}
}
我可以编辑包含“令人讨厌”类的库,但是,我不想破坏已经在使用该库的其他应用程序。如果涉及修改库代码的答案没有破坏已经在使用该库的其他应用程序,则将被接受。
在小提琴上测试:https://dotnetfiddle.net/RyxMjm
利用我从重复问题的答案中学到的知识,我创建了以下扩展方法,以允许应用程序代码将替代JsonConverter快速应用于其序列化程序。只有在极少数情况下,应用程序代码已经将另一个ContractResolver
应用于序列化程序设置对象,它才能破坏应用程序代码。
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SomeNameSpace {
public static class SerializerSettingsExtensions {
public static void UseAlternateConverterForSomeClass(this JsonSerializerSettings settings, JsonConverter jsonConverter) {
settings.ContractResolver = ConverterDisablingContractResolver.Instance;
settings.Converters.Add(jsonConverter);
}
private class ConverterDisablingContractResolver : DefaultContractResolver {
public static readonly ConverterDisablingContractResolver Instance = new ConverterDisablingContractResolver();
private ConverterDisablingContractResolver() { }
protected override JsonConverter ResolveContractConverter(Type objectType) {
if (objectType == typeof(SomeClass)) return null;
return base.ResolveContractConverter(objectType);
}
}
}
}