.NET 8中如何声明TypeConverter控制类序列化以兼容现有API响应
问题
我有一个已上线的ASP.NET Core 8 Web API项目,希望修改返回类型,但不能更改现有响应JSON格式(因为服务已投入生产)。
原有Web方法示例:
public async Task<JsonResult> InsertItem(InsertItemInput oInputParams) { Stopwatch oStopWatch = Stopwatch.StartNew(); int iResult = 0; iResult = // 数据库插入逻辑 return new JsonResult(new { StatusCode = (int)HttpStatusCode.OK, Exception = (object)null, Result = iResult, ServiceFullElapsed = oStopWatch.Elapsed.TotalMilliseconds }); }
返回的JSON格式:
{ "StatusCode": 200, "Exception": null, "Result": 157, "ServiceFullElapsed": 140.2169 }
我为结果创建了模型类:
[TypeConverter(typeof(ReadWriteResultJsonConvert))] public class ReadWriteResult { public int Code { get; set; } }
对应的转换器类:
public class ReadWriteResultJsonConvert : Newtonsoft.Json.JsonConverter<ReadWriteResult> { public override void WriteJson(JsonWriter writer, ReadWriteResult value, Newtonsoft.Json.JsonSerializer serializer) { var obj = (JObject)JToken.FromObject(value.Code); obj.WriteTo(writer); } public override ReadWriteResult ReadJson(JsonReader reader, Type objectType, ReadWriteResult existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer) { return existingValue; } }
修改后的Web方法:
public async Task<JsonResult> InsertItem(InsertItemInput oInputParams) { Stopwatch oStopWatch = Stopwatch.StartNew(); ReadWriteResult oResult = new ReadWriteResult(); oResult.Code = // 数据库插入逻辑 return new JsonResult(new { StatusCode = (int)HttpStatusCode.OK, Exception = (object)null, Result = oResult, ServiceFullElapsed = oStopWatch.Elapsed.TotalMilliseconds }); }
但转换器从未被调用,返回结果变成了:
{ "StatusCode": 200, "Exception": null, "Result": { "Code": 157 }, "ServiceFullElapsed": 28064.9097 }
我希望返回"Result":157而非"Result": { "Code": 157 },请问如何让ReadWriteResult类序列化时仅输出Code属性的值?
解决方案
方法1:修正Newtonsoft.Json转换器配置
你误用了[TypeConverter]特性,它是用于.NET原生类型转换的,并非Newtonsoft.Json的序列化标记。需要改用[JsonConverter]特性标记模型类,同时简化转换器逻辑:
// 替换TypeConverter为JsonConverter特性 [JsonConverter(typeof(ReadWriteResultJsonConvert))] public class ReadWriteResult { public int Code { get; set; } }
修正转换器的WriteJson方法,直接写入整数即可:
public class ReadWriteResultJsonConvert : Newtonsoft.Json.JsonConverter<ReadWriteResult> { public override void WriteJson(JsonWriter writer, ReadWriteResult value, Newtonsoft.Json.JsonSerializer serializer) { // 直接输出Code的整数值 writer.WriteValue(value.Code); } public override ReadWriteResult ReadJson(JsonReader reader, Type objectType, ReadWriteResult existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer) { // 反序列化时从整数还原对象 if (reader.TokenType == JsonToken.Integer) { return new ReadWriteResult { Code = (int)reader.Value }; } return existingValue ?? new ReadWriteResult(); } }
方法2:添加隐式类型转换
如果不想用转换器,可以给ReadWriteResult类添加隐式转换为int的逻辑,这样赋值时可直接把对象当作整数使用:
public class ReadWriteResult { public int Code { get; set; } // 隐式转换为int public static implicit operator int(ReadWriteResult result) { return result.Code; } // 可选:支持从int转换为ReadWriteResult public static implicit operator ReadWriteResult(int code) { return new ReadWriteResult { Code = code }; } }
修改Web方法中的Result赋值(可显式转换或依赖隐式自动转换):
return new JsonResult(new { StatusCode = (int)HttpStatusCode.OK, Exception = (object)null, Result = (int)oResult, ServiceFullElapsed = oStopWatch.Elapsed.TotalMilliseconds });
方法3:适配System.Text.Json(ASP.NET Core 8默认序列化器)
如果项目使用的是System.Text.Json而非Newtonsoft.Json,需要编写对应的转换器:
[System.Text.Json.Serialization.JsonConverter(typeof(ReadWriteResultSystemTextJsonConverter))] public class ReadWriteResult { public int Code { get; set; } } public class ReadWriteResultSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<ReadWriteResult> { public override ReadWriteResult Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.Number) { return new ReadWriteResult { Code = reader.GetInt32() }; } return default; } public override void Write(Utf8JsonWriter writer, ReadWriteResult value, JsonSerializerOptions options) { writer.WriteNumberValue(value.Code); } }
内容的提问来源于stack exchange,提问作者FDB
相关产品推荐
相关产品推荐

