如何为Swagger示例类单独配置Newtonsoft JSON.NET序列化设置?
为Swagger UI单独配置Newtonsoft JSON序列化设置(ASP.NET Core .NET 8)
问题场景
在ASP.NET Core(.NET 8)项目中使用Newtonsoft JSON.NET处理对象序列化,全局配置开启了PreserveReferencesHandling.Objects以兼容外部服务的层级数据,但Swagger UI展示的POST/PATCH请求示例会自动带上$id属性,导致使用者困惑。需要保留全局序列化配置的同时,单独为Swagger示例修改序列化规则,移除$id。
背景说明
- 必须使用JSON.NET的原因:微软内置JSON序列化无法处理外部服务返回的含未转义换行符的字符串属性,JSON.NET可灵活处理这类非规范数据。
- 当前全局MVC JSON配置:
builder.Services .AddControllers() .AddNewtonsoftJson ( options => { options.SerializerSettings.Converters.Add(new StringEnumConverter()); options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; options.SerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat; // 不可修改,否则无法序列化层级数据 options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects; } );
- 当前Swagger示例问题:
实际展示的JSON示例:
{ "$id":"1", "displayName":"Fonzie Fans", "description": "Everyone who likes Fonzie." }
期望展示的JSON示例:
{ "displayName":"Fonzie Fans", "description": "Everyone who likes Fonzie." }
可行解决方案
方法1:自定义示例提供器时手动序列化(推荐)
直接在IExamplesProvider实现中,使用独立的JsonSerializerSettings序列化对象为JSON字符串,确保Swagger展示的示例无$id。
- 修改示例提供器类,返回序列化后的JSON字符串:
public class GroupRequestCreateExample : IExamplesProvider<string> { public string GetExamples() { var group = new Group { DisplayName = "Fonzie Fans", Description = "Everyone who likes Fonzie." }; // 单独配置Swagger示例专用的序列化规则 var swaggerSerializerSettings = new JsonSerializerSettings { Converters = { new StringEnumConverter() }, NullValueHandling = NullValueHandling.Ignore, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, DateFormatHandling = DateFormatHandling.IsoDateFormat, // 关闭引用保留,移除$id属性 PreserveReferencesHandling = PreserveReferencesHandling.None }; return JsonConvert.SerializeObject(group, swaggerSerializerSettings); } }
- 在Swagger配置中,指定示例的媒体类型为
application/json,确保Swagger UI正确解析字符串为JSON格式:
builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "你的API名称", Version = "v1" }); // 注册示例过滤器和程序集中的示例类 c.ExampleFilters(); c.AddSwaggerExamplesFromAssemblyOf<GroupRequestCreateExample>(); // 配置字符串类型示例映射为JSON对象 c.MapType<string>(() => new OpenApiSchema { Type = "object", Format = "json" }); });
方法2:全局替换Swagger的序列化器
通过修改Swagger使用的SchemaGenerator,让所有Swagger示例使用独立的序列化配置。
- 定义Swagger专用的JSON序列化设置:
public static class SwaggerJsonSerializerSettings { public static JsonSerializerSettings GetSettings() { return new JsonSerializerSettings { Converters = { new StringEnumConverter() }, NullValueHandling = NullValueHandling.Ignore, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, DateFormatHandling = DateFormatHandling.IsoDateFormat, PreserveReferencesHandling = PreserveReferencesHandling.None }; } }
- 在Swagger配置中替换默认的SchemaGenerator:
builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "你的API名称", Version = "v1" }); // 替换为使用自定义序列化设置的SchemaGenerator c.SchemaGenerator = new SchemaGenerator(new SchemaGeneratorSettings { SerializerSettings = SwaggerJsonSerializerSettings.GetSettings() }); // 注册示例过滤器和示例类 c.ExampleFilters(); c.AddSwaggerExamplesFromAssemblyOf<GroupRequestCreateExample>(); });
注意事项
- 方法1灵活性更高,可针对单个示例类单独配置序列化规则,不影响其他类型的Swagger示例;
- 方法2是全局修改Swagger的序列化逻辑,所有生成的示例都会使用该配置;
- 两种方法均不会影响MVC控制器的全局序列化配置,确保接收外部层级数据的逻辑正常运行。
内容的提问来源于stack exchange,提问作者Alek Davis
相关产品推荐
相关产品推荐

