问题描述
我正在制作 Core 3.1 Web API 并使用 JsonPatch 创建 PATCH 操作。我有一个名为 Patch
的操作,它有一个 JsonPatchDocument
参数。这是动作的签名:
[HttpPatch("{id}")]
public ActionResult<FileRecordDto> Patch(int id,[FromBody] JsonPatchDocument<FileRecordQueryParams> patchDoc)
据我所知,该参数需要接收以下结构的 JSON 数据,我已成功使用该操作对其进行了测试:
[
{
"op": "operationName","path": "/propertyName","value": "newPropertyValue"
}
]
我对这种结构并不熟悉,甚至其中还缺少 "value"
对象所具有的 JsonPatchDocument
属性。我见过的每个使用 replace
操作修补的示例都具有第一个结构。
为什么 Swagger 为 PATCH 端点的请求正文中的 JsonPatchDocument
对象生成替代结构?我该如何解决这个问题?
解决方法
Swashbuckle.AspNetCore
不适用于此类型 JsonPatchDocument<UpdateModel>
,它不代表预期的补丁请求文件。
您需要自定义文档过滤器来修改生成的规范。
public class JsonPatchDocumentFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc,DocumentFilterContext context)
{
var schemas = swaggerDoc.Components.Schemas.ToList();
foreach (var item in schemas)
{
if (item.Key.StartsWith("Operation") || item.Key.StartsWith("JsonPatchDocument"))
swaggerDoc.Components.Schemas.Remove(item.Key);
}
swaggerDoc.Components.Schemas.Add("Operation",new OpenApiSchema
{
Type = "object",Properties = new Dictionary<string,OpenApiSchema>
{
{"op",new OpenApiSchema{ Type = "string" } },{"value",new OpenApiSchema{ Type = "string"} },{"path",new OpenApiSchema{ Type = "string" } }
}
});
swaggerDoc.Components.Schemas.Add("JsonPatchDocument",new OpenApiSchema
{
Type = "array",Items = new OpenApiSchema
{
Reference = new OpenApiReference { Type = ReferenceType.Schema,Id = "Operation" }
},Description = "Array of operations to perform"
});
foreach (var path in swaggerDoc.Paths.SelectMany(p => p.Value.Operations)
.Where(p => p.Key == Microsoft.OpenApi.Models.OperationType.Patch))
{
foreach (var item in path.Value.RequestBody.Content.Where(c => c.Key != "application/json-patch+json"))
path.Value.RequestBody.Content.Remove(item.Key);
var response = path.Value.RequestBody.Content.Single(c => c.Key == "application/json-patch+json");
response.Value.Schema = new OpenApiSchema
{
Reference = new OpenApiReference { Type = ReferenceType.Schema,Id = "JsonPatchDocument" }
};
}
}
}
注册过滤器:
services.AddSwaggerGen(c => c.DocumentFilter<JsonPatchDocumentFilter>());
结果: