我注意到一些让我吃惊的行为。我有一个抽象基类和一个派生类。
[JsonPolymorphic]
[JsonDerivedType(typeof(DerivedClass), "derived")]
public abstract class BaseClass
{
public BaseClass() { }
}
public class DerivedClass : BaseClass
{
public string? Whatever { get; set; }
}
字符串
现在我有了两个JSON字符串:第一个JSON字符串的第一个属性是类型$type
,第二个JSON字符串没有。当我执行JsonSerializer.Deserialize<BaseClass>()
时,第二个JSON字符串会抛出一个异常。
var jsonWorks = "{\"$type\": \"derived\", \"whatever\": \"Bar\"}";
var jsonBreaks = "{\"whatever\": \"Bar\", \"$type\": \"derived\"}";
var obj1 = JsonSerializer.Deserialize<BaseClass>(jsonWorks);
var obj2 = JsonSerializer.Deserialize<BaseClass>(jsonBreaks); // This one will throw an exception
型
抛出的异常类型为System.NotSupportedException
,消息如下:
System.NotSupportedException: 'Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'MyApp.BaseClass'. Path: $ | LineNumber: 0 | BytePositionInLine: 12.'
型
它也有一个内部异常:
NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'MyApp.BaseClass'.
型
这是预期的行为,还是实际上是System.Text.Json
中的一个潜在错误?这已经在net8.0
中尝试过了。
1条答案
按热度按时间cwtwac6a1#
从.NET 8开始,这是System.Text.JSON的一个有记录的限制。来自多态类型判别器:
备注
必须将类型放在JSON对象的开头,与其他元数据属性(如
$id
和$ref
)分组在一起。如果由于某种原因,您无法在常规属性之前序列化元数据属性,则需要在序列化之前手动修复JSON,例如通过预加载到
JsonNode
层次结构中并递归修复属性顺序。为此,首先定义以下扩展方法:
字符串
然后你可以做:
型
备注:
"$type"
。如果使用不同的类型判别器,请将适当的 predicate 传递给重载:
型
MetadataPropertyHandling.ReadAhead
来克服。演示小提琴here。