如何在ASP.NET Core API中返回无需二次序列化的JSON字符串
解决方案:直接透传预序列化的JSON字符串
刚好遇到过类似的场景,给你几个高效的方案,不用做多余的反序列化→序列化操作,就能让Data字段直接以原始JSON形式输出,避免转义:
方法一:使用Json.NET(ASP.NET Core 2.0默认)自定义转换器
ASP.NET Core 2.0默认用的是Json.NET(Newtonsoft.Json),我们可以写一个自定义转换器,告诉序列化器直接把Data的字符串内容当成原始JSON写入:
1. 实现自定义JsonConverter
public class RawJsonStringConverter : JsonConverter<string> { // 反序列化逻辑(如果需要接收这类数据的话) public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.String) { return (string)reader.Value; } // 如果传入的是原始JSON对象,直接转成字符串返回 using (var sw = new StringWriter()) using (var jw = new JsonTextWriter(sw)) { jw.WriteToken(reader); return sw.ToString(); } } // 核心:序列化时直接写入原始JSON,跳过转义 public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer) { writer.WriteRawValue(value); } }
2. 给Data属性标记转换器
修改你的ResponseModel,给Data加上转换器特性:
public class ResponseModel { public Guid Id { get; set; } public DateTime TimesStamp { get; set; } [JsonConverter(typeof(RawJsonStringConverter))] public string Data { get; set; } }
这样当API返回ResponseModel时,Data的内容会直接作为JSON的一部分输出,不会被转义成带引号的字符串。
方法二:使用System.Text.Json(ASP.NET Core 3.0+)的方案
如果你的项目升级到了ASP.NET Core 3.0+,用的是默认的System.Text.Json,有两种选择:
选项1:用JsonElement替代string(轻量级反序列化)
JsonElement是System.Text.Json里的轻量级JSON节点类型,开销远小于object,可以直接把原始JSON字符串解析成JsonElement:
public class ResponseModel { public Guid Id { get; set; } public DateTime TimesStamp { get; set; } public JsonElement Data { get; set; } }
赋值的时候只需做一次轻量级解析:
var rawJson = "{\"name\":\"test\",\"value\":123}"; var response = new ResponseModel { Id = Guid.NewGuid(), TimesStamp = DateTime.UtcNow, Data = JsonSerializer.Deserialize<JsonElement>(rawJson) };
选项2:自定义System.Text.Json转换器
如果还是想用string类型的Data,可以写对应的自定义转换器:
public class RawJsonStringConverter : JsonConverter<string> { public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { return reader.GetString(); } using (var doc = JsonDocument.ParseValue(ref reader)) { return doc.RootElement.GetRawText(); } } public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) { // 直接写入原始JSON内容 writer.WriteRawValue(value); } }
然后在Startup里全局注册转换器,或者给Data属性单独标记:
// 全局注册 services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new RawJsonStringConverter()); }); // 或者单独标记属性 [JsonConverter(typeof(RawJsonStringConverter))] public string Data { get; set; }
注意事项
- 一定要确保
Data的内容是有效的JSON格式,否则会导致整个响应的JSON结构损坏。可以在赋值前用JsonDocument.TryParse(System.Text.Json)或JToken.Parse(Json.NET)做验证。 - 因为你不需要内容协商,这些方案都只针对JSON输出,完全符合你的需求。
内容的提问来源于stack exchange,提问作者peter
相关产品推荐
相关产品推荐

