Skip to content

Commit 03bea8e

Browse files
committed
Add annotation to hide underlying resource ID type in OpenAPI document
1 parent 2554891 commit 03bea8e

File tree

3 files changed

+43
-9
lines changed

3 files changed

+43
-9
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace JsonApiDotNetCore.OpenApi.Swashbuckle.Annotations;
2+
3+
/// <summary>
4+
/// Hides the underlying resource ID type in OpenAPI documents.
5+
/// </summary>
6+
/// <remarks>
7+
/// For example, when used on a resource type that implements <c><![CDATA[IIdentifiable<long>]]></c>, excludes the <c>format</c> property on the ID
8+
/// schema. As a result, the ID type is displayed as <c>string</c> instead of
9+
/// <c>
10+
/// string($int64)
11+
/// </c>
12+
/// in SwaggerUI.
13+
/// </remarks>
14+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct)]
15+
public sealed class HideResourceIdTypeInOpenApiAttribute : Attribute;

src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceIdSchemaGenerator.cs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
using System.Reflection;
12
using JsonApiDotNetCore.Configuration;
3+
using JsonApiDotNetCore.Middleware;
4+
using JsonApiDotNetCore.OpenApi.Swashbuckle.Annotations;
25
using Microsoft.OpenApi.Models;
36
using Swashbuckle.AspNetCore.SwaggerGen;
47

@@ -7,32 +10,48 @@ namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components;
710
internal sealed class ResourceIdSchemaGenerator
811
{
912
private readonly SchemaGenerator _defaultSchemaGenerator;
13+
private readonly IControllerResourceMapping _controllerResourceMapping;
1014

11-
public ResourceIdSchemaGenerator(SchemaGenerator defaultSchemaGenerator)
15+
public ResourceIdSchemaGenerator(SchemaGenerator defaultSchemaGenerator, IControllerResourceMapping controllerResourceMapping)
1216
{
1317
ArgumentNullException.ThrowIfNull(defaultSchemaGenerator);
18+
ArgumentNullException.ThrowIfNull(controllerResourceMapping);
1419

1520
_defaultSchemaGenerator = defaultSchemaGenerator;
21+
_controllerResourceMapping = controllerResourceMapping;
1622
}
1723

18-
public OpenApiSchema GenerateSchema(ResourceType resourceType, SchemaRepository schemaRepository)
24+
public OpenApiSchema GenerateSchema(ParameterInfo parameter, SchemaRepository schemaRepository)
1925
{
20-
ArgumentNullException.ThrowIfNull(resourceType);
26+
ArgumentNullException.ThrowIfNull(parameter);
27+
ArgumentNullException.ThrowIfNull(schemaRepository);
28+
29+
Type? controllerType = parameter.Member.ReflectedType;
30+
ConsistencyGuard.ThrowIf(controllerType == null);
31+
32+
ResourceType? resourceType = _controllerResourceMapping.GetResourceTypeForController(controllerType);
33+
ConsistencyGuard.ThrowIf(resourceType == null);
2134

22-
return GenerateSchema(resourceType.IdentityClrType, schemaRepository);
35+
return GenerateSchema(resourceType, schemaRepository);
2336
}
2437

25-
public OpenApiSchema GenerateSchema(Type resourceIdClrType, SchemaRepository schemaRepository)
38+
public OpenApiSchema GenerateSchema(ResourceType resourceType, SchemaRepository schemaRepository)
2639
{
27-
ArgumentNullException.ThrowIfNull(resourceIdClrType);
40+
ArgumentNullException.ThrowIfNull(resourceType);
2841
ArgumentNullException.ThrowIfNull(schemaRepository);
2942

30-
OpenApiSchema idSchema = _defaultSchemaGenerator.GenerateSchema(resourceIdClrType, schemaRepository);
43+
OpenApiSchema idSchema = _defaultSchemaGenerator.GenerateSchema(resourceType.IdentityClrType, schemaRepository);
3144
ConsistencyGuard.ThrowIf(idSchema.Reference != null);
3245

3346
idSchema.Type = "string";
3447

35-
if (resourceIdClrType != typeof(string))
48+
var hideIdTypeAttribute = resourceType.ClrType.GetCustomAttribute<HideResourceIdTypeInOpenApiAttribute>();
49+
50+
if (hideIdTypeAttribute != null)
51+
{
52+
idSchema.Format = null;
53+
}
54+
else if (resourceType.IdentityClrType != typeof(string))
3655
{
3756
// When using string IDs, it's discouraged (but possible) to use an empty string as primary key value, because
3857
// some things won't work: get-by-id, update and delete resource are impossible, and rendered links are unusable.

src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/JsonApiSchemaGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public OpenApiSchema GenerateSchema(Type schemaType, SchemaRepository schemaRepo
3434

3535
if (parameterInfo is { Name: "id" } && IsJsonApiParameter(parameterInfo))
3636
{
37-
return _resourceIdSchemaGenerator.GenerateSchema(schemaType, schemaRepository);
37+
return _resourceIdSchemaGenerator.GenerateSchema(parameterInfo, schemaRepository);
3838
}
3939

4040
DocumentSchemaGenerator? schemaGenerator = GetDocumentSchemaGenerator(schemaType);

0 commit comments

Comments
 (0)