在某些上下文(如多态性和引用保留)下, System.Text.Json 保留用于发出元数据的特定属性名称(例如 $type, $id和 $ref)。 还可以使用自定义名称配置某些属性名称,例如 TypeDiscriminatorPropertyName 。 以前,序列化程序没有验证这些属性名称是否与用户定义的协定冲突,这可能会导致重复的属性,并生成不明确或无法进行往返序列化的 JSON。 从 .NET 10 开始,System.Text.Json 支持验证以防止此类配置,并为用户提供预警。
引入的版本
.NET 10
以前的行为
以前,以下代码生成了具有重复 Type 属性的无效 JSON 对象,并且无法使用以下命令 JsonException反序列化:
using System.Text.Json;
using System.Text.Json.Serialization;
string json = JsonSerializer.Serialize<Animal>(new Dog());
Console.WriteLine(json); // {"Type":"dog","Type":"Dog"}
JsonSerializer.Deserialize<Animal>(json); // JsonException: Deserialized object contains a duplicate 'Type' metadata property.
[JsonPolymorphic(TypeDiscriminatorPropertyName = "Type")]
[JsonDerivedType(typeof(Dog), "dog")]
public abstract class Animal
{
public abstract string Type { get; }
}
public class Dog : Animal
{
public override string Type => "Dog";
}
新行为
从 .NET 10 开始,任何序列化同一类型的尝试都会导致早期验证错误:
无效操作异常:类型“Dog”包含与现有元数据属性名称冲突的属性“Type”。 请考虑重命名它或使用 JsonIgnoreAttribute 将其忽略。
首次创建序列化程序或首次尝试序列化时,会发生此验证错误,从而提前检测无效的序列化协定。
破坏性变更的类型
此更改为行为更改。
更改原因
此更改可提前防止无效序列化协定。 通过预先验证属性名称,序列化程序可防止输出重复属性,从而导致 JSON 无效,无法实现正确的往返传输。 这有助于开发人员在开发期间识别和修复配置问题,而不是在反序列化期间在运行时发现它们。
有关详细信息,请参见:
建议的措施
避免使用与特定于 System.Text.Json 的元数据属性(例如 $type, $id和 $ref)冲突的属性名称。 如果绝对有必要在类中保留此类属性,请对冲突属性应用 JsonIgnoreAttribute 批注。