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::GetOperationName
method中定义的。在某些情况下,此逻辑会在依赖 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) => ...,
});
使用 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::GetOperationName
method中定义的。在某些情况下,此逻辑会在依赖 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) => ...,
});