小提琴测试: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);
}
}
}
}