ServiceStack - 使用 OpenApiFeature 自定义生成的 OpenAPI JSON

ServiceStack - Customize Generated OpenAPI JSON using OpenApiFeature

使用 ServiceStack OpenApiFeature,在 openapi.json 文件中生成的 operationId 遵循以下约定:

[RequestName][route path slice without first path*][http verb][digit if required for uniqueness]

没有第一条路径的路由路径切片*只是删除路径中的第一项。所以如果路由路径是blog/author/name,逻辑会抓取author/name.

这是在OpenApiService::GetOperationNamemethod中定义的。在某些情况下,此逻辑会在依赖 openapi.json 的工具中创建次优操作命名。例如,如果您有一项服务公开了针对客户详细信息、客户摘要等的 GET 操作,并且详细信息请求定义如下:

[Api("Get a customer's details.")]
[Route("/customer/details", "GET")]
public class GetCustomerDetailsRequest : IReturn<GetCustomerDetailsResponse>
{ ... }

路线将是这样的(这很好): /customer/details?customerId=2

...但是生成的 OpenAPI operationId 会是 GetCustomerDetailsRequestdetails_Get,这不是很好。

有没有办法使用 OpenApiFeature 自定义生成的 operationId?如果没有,是否有其他一些命名约定将保持 REST 式路由约定但提供更好的 OpenAPI operationId?

编辑: 感谢 mythz 指出 ApiDeclarationFilter。它允许您完全自定义生成的openapi.json。这就是我改变 operationId:

的方式
Plugins.Add(new OpenApiFeature
        {
            ApiDeclarationFilter = declaration =>
            {
                foreach (var p in declaration.Paths)
                {
                    foreach (var httpVerb in _httpVerbs) // _httpVerbs is just a list of http verbs
                    {
                        // retrieve the operation value using reflection and pattern matching.  This is to prevent having to use a switch statement to go through each http verb and check if it's been implemented
                        if (p.Value.GetType().GetProperty(httpVerb).GetValue(p.Value) is OpenApiOperation operation)
                        {
                            // Set the "OperationId" property using the convention [RequestClassName]_[Http Verb].  Note for simplicity here, I'm not checking for a unique operation Id.  You should do that to ensure open api compliance
                            ReflectionHelper.SetProperty($"{httpVerb}.OperationId", p.Value,
                                $"{operation.RequestType}_{httpVerb}");
                        }
                    }
                }
            }
        });

除了API metadata attributes, you can further customize what JSON is returned using the filters available,例如:

Plugins.Add(new OpenApiFeature
{
    ApiDeclarationFilter = (openApiDoc) => ...,
    OperationFilter = (verb, operation) => ...,
    SchemaFilter = (schema) => ...,
    SchemaPropertyFilter = (openApiProperty) => ...,
});