如何用System.Text.Json实现同一类序列化反序列化不同属性名?
解决System.Text.Json序列化/反序列化分别指定属性名的问题
核心需求
同一个模型类,反序列化外部API的JSON时使用外部字段名(如event_id、ourName),序列化返回给客户端时使用类自身的属性名(如id、name),无需额外创建映射模型或手动赋值。
可行方案
方案一:自定义JsonConverter(针对单个类)
适合仅需处理少数类的场景,直接控制序列化的输出字段名。
- 定义模型类:用
JsonPropertyName指定外部API的字段名,属性名保留客户端需要的名称:
public class Event { [JsonPropertyName("event_id")] public int Id { get; set; } [JsonPropertyName("ourName")] public string Name { get; set; } }
- 创建自定义转换器:反序列化时默认处理(尊重
JsonPropertyName),序列化时手动写入属性原名:
public class EventConverter : JsonConverter<Event> { public override Event Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return JsonSerializer.Deserialize<Event>(ref reader, options); } public override void Write(Utf8JsonWriter writer, Event value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WriteNumber("id", value.Id); writer.WriteString("name", value.Name); writer.WriteEndObject(); } }
- 使用方式:
// 反序列化外部API响应 var externalJson = "{ \"event_id\": 1, \"ourName\" : \"Test\" }"; var eventModel = JsonSerializer.Deserialize<Event>(externalJson); // 序列化返回给客户端 var clientOptions = new JsonSerializerOptions(); clientOptions.Converters.Add(new EventConverter()); var clientJson = JsonSerializer.Serialize(eventModel, clientOptions); // 输出结果:{"id":1,"name":"Test"}
方案二:通用型TypeInfoResolver配置(推荐)
无需为每个类写转换器,通过修改类型信息统一处理所有类的序列化名称,更适合多类场景。
- 创建自定义TypeInfoResolver:
var clientTypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Kind != JsonTypeInfoKind.Object) return; foreach (var property in typeInfo.Properties) { // 将序列化时的字段名强制改为类属性的原名 property.Name = property.PropertyInfo?.Name ?? property.Name; } } } };
- 配置序列化选项并使用:
// 反序列化外部API(使用默认配置,尊重JsonPropertyName) var externalJson = "{ \"event_id\": 1, \"ourName\" : \"Test\" }"; var eventModel = JsonSerializer.Deserialize<Event>(externalJson); // 序列化给客户端(使用自定义TypeInfoResolver) var clientOptions = new JsonSerializerOptions { TypeInfoResolver = clientTypeInfoResolver }; var clientJson = JsonSerializer.Serialize(eventModel, clientOptions);
这种方式会自动遍历类的所有属性,序列化时直接使用属性原名,反序列化时依然遵循JsonPropertyName指定的外部字段名,完美匹配需求。
内容的提问来源于stack exchange,提问作者RoLYroLLs
相关产品推荐
相关产品推荐

