In my 的原始版本DefaultConverterFactory<T> https://stackoverflow.com/revisions/65430421/3,我缓存了默认转换器,因为在其文档中如何在 .NET 中编写用于 JSON 序列化(编组)的自定义转换器 https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to#sample-factory-pattern-converter,出于性能原因,Microsoft 建议在序列化复杂对象时缓存任何所需的转换器:
public DictionaryEnumConverterInner(JsonSerializerOptions options)
{
// For performance, use the existing converter if available.
_valueConverter = (JsonConverter<TValue>)options
.GetConverter(typeof(TValue));
// Cache the key and value types.
_keyType = typeof(TKey);
_valueType = typeof(TValue);
}
然而,由于以下几个原因,这已被证明是有问题的:
-
当使用 a 序列化多态值时declared类型object
,返回一个非功能转换器GetConverter()
.
-
序列化数值时,返回的转换器会忽略NumberHandling https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.numberhandling?view=net-6.0#System_Text_Json_JsonSerializerOptions_NumberHandling环境。
-
现在看来您可能遇到了第三个问题:在使用时编译时序列化器源代码生成 https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-source-generation?pivots=dotnet-6-0,返回的转换器可能无法工作。
这些问题足以让我们忽略微软的建议。简单地DefaultConverter<T>
如下:
public abstract class DefaultConverterFactory<T> : JsonConverterFactory
{
class DefaultConverter : JsonConverter<T>
{
readonly JsonSerializerOptions modifiedOptions;
readonly DefaultConverterFactory<T> factory;
public DefaultConverter(JsonSerializerOptions options, DefaultConverterFactory<T> factory)
{
this.factory = factory;
this.modifiedOptions = options.CopyAndRemoveConverter(factory.GetType());
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) => factory.Write(writer, value, modifiedOptions);
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => factory.Read(ref reader, typeToConvert, modifiedOptions);
}
protected virtual T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions modifiedOptions)
=> (T)JsonSerializer.Deserialize(ref reader, typeToConvert, modifiedOptions);
protected virtual void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions modifiedOptions)
=> JsonSerializer.Serialize(writer, value, modifiedOptions);
public override bool CanConvert(Type typeToConvert) => typeof(T) == typeToConvert;
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) => new DefaultConverter(options, this);
}
public static class JsonSerializerExtensions
{
public static JsonSerializerOptions CopyAndRemoveConverter(this JsonSerializerOptions options, Type converterType)
{
var copy = new JsonSerializerOptions(options);
for (var i = copy.Converters.Count - 1; i >= 0; i--)
if (copy.Converters[i].GetType() == converterType)
copy.Converters.RemoveAt(i);
return copy;
}
}
然后,在任何派生自的类中DefaultConverterFactory<T>
例如这里这个 https://github.com/Meep-Tech/ActivityHub.Net/blob/collapse_links_during_serialization/Types/Link.cs#L188,去掉最后一个参数JsonConverter<T> defaultConverter
from Read()
and Write()
,您的代码现在应该可以工作了。
(顺便说一句,你似乎正在使用[JsonSerializable(typeof(Link))] https://github.com/Meep-Tech/ActivityHub.Net/blob/05d18532631b33ba765784078b2b95f91589ac1f/Types/Link.cs错。您正在将其应用到您的模型类中Link
但是,根据docs https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-source-generation?pivots=dotnet-6-0,它应该应用于某些子类JsonSerializerContext https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonserializercontext?view=net-6.0对于你的模型——而不是模型本身。)