System.Text.Json中XmlElementAttribute动态类型绑定的替代方案咨询
解决方案:自定义JSON转换器实现动态类型绑定
System.Text.Json没有提供和XmlElementAttribute完全对等的特性,要实现根据JSON属性名动态为ParentClass的Item属性分配对应类型的功能,需要自定义JsonConverter来处理序列化和反序列化逻辑。
实现步骤
1. 定义自定义转换器
创建继承自JsonConverter<ParentClass>的转换器类,在读取JSON时判断属性名并实例化对应类型;写入JSON时根据Item的类型输出对应属性名:
using System.Text.Json; using System.Text.Json.Serialization; public class ParentClassConverter : JsonConverter<ParentClass> { public override ParentClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) { throw new JsonException("JSON必须以对象开头"); } var parent = new ParentClass(); while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { break; } if (reader.TokenType != JsonTokenType.PropertyName) { continue; } string propertyName = reader.GetString()!; reader.Read(); switch (propertyName) { case "Location": parent.Location = reader.GetString(); break; case "Emp": parent.Item = JsonSerializer.Deserialize<Employee>(ref reader, options); break; case "Dept": parent.Item = JsonSerializer.Deserialize<Department>(ref reader, options); break; default: reader.Skip(); break; } } return parent; } public override void Write(Utf8JsonWriter writer, ParentClass value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WriteString("Location", value.Location); if (value.Item is Employee emp) { writer.WritePropertyName("Emp"); JsonSerializer.Serialize(writer, emp, options); } else if (value.Item is Department dept) { writer.WritePropertyName("Dept"); JsonSerializer.Serialize(writer, dept, options); } writer.WriteEndObject(); } }
2. 注册并使用转换器
在序列化或反序列化时,将自定义转换器添加到JsonSerializerOptions中即可:
反序列化示例
// 解析含Emp的JSON string empJson = @" { ""Location"": ""Chicago"", ""Emp"": { ""EmployeeID"":123, ""EmployeeName"":""Peter"" } }"; var options = new JsonSerializerOptions(); options.Converters.Add(new ParentClassConverter()); ParentClass empParent = JsonSerializer.Deserialize<ParentClass>(empJson, options); // empParent.Item 为 Employee 类型,属性值正确 // 解析含Dept的JSON string deptJson = @" { ""Location"": ""NJ"", ""Dept"": { ""DepartmentID"":567, ""DepartmentName"":""IT"" } }"; ParentClass deptParent = JsonSerializer.Deserialize<ParentClass>(deptJson, options); // deptParent.Item 为 Department 类型,属性值正确
序列化示例
// 序列化含Employee的ParentClass var empParent = new ParentClass { Location = "NY", Item = new Employee { EmployeeID = 456, EmployeeName = "Alice" } }; string serializedEmp = JsonSerializer.Serialize(empParent, options); // 输出JSON包含"Emp"属性 // 序列化含Department的ParentClass var deptParent = new ParentClass { Location = "LA", Item = new Department { DepartmentID = 890, DepartmentName = "HR" } }; string serializedDept = JsonSerializer.Serialize(deptParent, options); // 输出JSON包含"Dept"属性
扩展说明
如果后续需要支持更多类型,只需在转换器的Read和Write方法中添加对应的分支逻辑即可,扩展性较强。
内容的提问来源于stack exchange,提问作者Sravani Yadav
相关产品推荐
相关产品推荐

