编译错误是因为JsonPolymorphismOptions.DerivedTypes
是一个预分配的IList<JsonDerivedType>
类型的read-only collection property.因此,您不能将其赋给某些LINQ查询返回的值.
相反,您必须在构造后将派生类型添加到其中:
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options) {
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
Type baseValueObjectType = typeof(ValueObject);
if (jsonTypeInfo.Type == baseValueObjectType) {
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions {
TypeDiscriminatorPropertyName = "$mytype",
IgnoreUnrecognizedTypeDiscriminators = true,
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
};
var types = Assembly
.GetExecutingAssembly()
.GetTypes()
.Where(t => t.IsSubclassOf(typeof(ValueObject))); // Fixed MyBaseClass => ValueObject
foreach (var t in types.Select(t => new JsonDerivedType(t, t.Name.ToLowerInvariant()))) // Fixed ToLower() => ToLowerInvariant
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(t);
}
return jsonTypeInfo;
}
here.第一次见面
请注意,从.NET8开始,我建议您使用JsonTypeInfo
modifier而不是子类化DefaultJsonTypeInfoResolver
,因为WithAddedModifier()
可以处理包括source-generated contexts在内的任意IJsonTypeInfoResolver
个实例.
为此,首先定义以下扩展方法:
public static class JsonExtensions
{
public static void AddNativePolymorphicTypInfo(JsonTypeInfo jsonTypeInfo)
{
Type baseValueObjectType = typeof(ValueObject);
if (jsonTypeInfo.Type == baseValueObjectType) {
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions {
TypeDiscriminatorPropertyName = "$mytype",
IgnoreUnrecognizedTypeDiscriminators = true,
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
};
var types = Assembly
.GetExecutingAssembly()
.GetTypes()
.Where(t => t.IsSubclassOf(typeof(ValueObject))); // Fixed MyBaseClass => ValueObject
foreach (var t in types.Select(t => new JsonDerivedType(t, t.Name.ToLowerInvariant()))) // Fixed ToLower() => ToLowerInvariant
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(t);
}
}
}
然后设置选项,例如,如下所示:
var options = new JsonSerializerOptions
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver() // Or use some source-generated context if you prefer
.WithAddedModifier(JsonExtensions.AddNativePolymorphicTypInfo),
// Add other options as required, e.g.
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
var json = JsonSerializer.Serialize(rootObject, options);
演示小提琴#2here.
node :
Update个
在您的modified fiddle from comments中,您希望在序列化声明为ValueObject
的子类型的值时,使用上面的AddNativePolymorphicTypInfo()
版本自动添加多态类型鉴别器.在您的问题所示的代码中,您可以通过以下判断来防止出现这种情况:
if (jsonTypeInfo.Type == baseValueObjectType)
你需要判断一下
typeof(ValueObject).IsAssignableFrom(jsonTypeInfo.Type)
如果要将多态鉴别器自动添加到ValueObject
的所有派生类型,即使在将其显式序列化为派生类型时也是如此,则必须按如下方式修改AddNativePolymorphicTypInfo()
:
public static class JsonExtensions
{
public static void AddNativePolymorphicTypInfo(JsonTypeInfo jsonTypeInfo)
{
if (typeof(ValueObject).IsAssignableFrom(jsonTypeInfo.Type) && !jsonTypeInfo.Type.IsSealed) {
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions {
TypeDiscriminatorPropertyName = "$mytype",
IgnoreUnrecognizedTypeDiscriminators = true,
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
};
// This query is likely to be slow so you might want to cache all types assignable to typeof(ValueObject) in a lazy static singleton
var types = Assembly
.GetExecutingAssembly()
.GetTypes()
.Where(t => !t.IsAbstract && jsonTypeInfo.Type.IsAssignableFrom(t));
foreach (var t in types.Select(t => new JsonDerivedType(t, t.Name.ToLowerInvariant()))) // Fixed ToLower() => ToLowerInvariant
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(t);
}
}
}
但是,请注意,在序列化声明为sealed
个类型的值时,System.Text.Json不允许发出多态类型标识符.如果您的任何派生ValueObject
类型是密封的,则必须使用不同的方法,例如将鉴别器作为合成属性插入.
here. history of life