Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ed21fc7

Browse files
committed
Add support for OpenAPI.NET 2.0
1 parent a3ea095 commit ed21fc7

33 files changed

+306
-190
lines changed

‎package-versions.props

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@
3333
<PropertyGroup Condition="'$(TargetFramework)' == 'net10.0'">
3434
<!-- Published dependencies (only update on major version change) -->
3535
<EntityFrameworkCoreFrozenVersion>10.0.*-*</EntityFrameworkCoreFrozenVersion>
36+
<SwashbuckleFrozenVersion>9.0.0-pr.3283.*</SwashbuckleFrozenVersion>
3637

3738
<!-- Non-published dependencies (these are safe to update, won't cause a breaking change) -->
3839
<AspNetCoreVersion>10.0.*-*</AspNetCoreVersion>
40+
<SwashbuckleVersion>9.0.0-pr.3283.*</SwashbuckleVersion>
41+
<MicrosoftApiServerVersion>10.0.*-*</MicrosoftApiServerVersion>
3942
<EntityFrameworkCoreVersion>10.0.*-*</EntityFrameworkCoreVersion>
4043
<EntityFrameworkCorePomeloVersion>9.0.*-*</EntityFrameworkCorePomeloVersion>
4144
</PropertyGroup>

‎src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22
<PropertyGroup>
3-
<TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>
3+
<TargetFrameworks>net10.0</TargetFrameworks>
44
<OpenApiGenerateDocumentsOnBuild>true</OpenApiGenerateDocumentsOnBuild>
55
<OpenApiDocumentsDirectory>GeneratedSwagger</OpenApiDocumentsDirectory>
66
</PropertyGroup>

‎src/Examples/JsonApiDotNetCoreExample/SetOpenApiServerAtBuildTimeFilter.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
1616
{
1717
if (_httpContextAccessor.HttpContext == null)
1818
{
19+
swaggerDoc.Servers ??= new List<OpenApiServer>();
20+
1921
swaggerDoc.Servers.Add(new OpenApiServer
2022
{
2123
Url = "https://localhost:44340"

‎src/JsonApiDotNetCore.OpenApi.Swashbuckle/ConfigureSwaggerGenOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ public void Configure(SwaggerGenOptions options)
7474
options.DocumentFilter<StringEnumOrderingFilter>();
7575
options.DocumentFilter<SetSchemaTypeToObjectDocumentFilter>();
7676
options.DocumentFilter<UnusedComponentSchemaCleaner>();
77+
options.DocumentFilter<SortSchemasFilter>();
7778
}
7879

7980
private List<Type> SelectDerivedTypes(Type baseType)

‎src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFrameworks>net10.0;net8.0</TargetFrameworks>
3+
<TargetFrameworks>net10.0</TargetFrameworks>
44
<IsPackable>true</IsPackable>
55
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
66
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Microsoft.OpenApi.Models;
2+
3+
namespace JsonApiDotNetCore.OpenApi.Swashbuckle;
4+
5+
internal static class MicrosoftOpenApiCompatibilityExtensions
6+
{
7+
public static void SetNullable(this OpenApiSchema schema, bool nullable)
8+
{
9+
ArgumentNullException.ThrowIfNull(schema);
10+
11+
if (nullable)
12+
{
13+
schema.Type ??= JsonSchemaType.Null;
14+
schema.Type |= JsonSchemaType.Null;
15+
}
16+
else
17+
{
18+
if (schema.Type != null)
19+
{
20+
schema.Type &= ~JsonSchemaType.Null;
21+
}
22+
}
23+
}
24+
}

‎src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiSchemaExtensions.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.OpenApi.Models;
2+
using Microsoft.OpenApi.Models.Interfaces;
23

34
namespace JsonApiDotNetCore.OpenApi.Swashbuckle;
45

@@ -9,7 +10,7 @@ public static void ReorderProperties(this OpenApiSchema fullSchema, IEnumerable<
910
ArgumentNullException.ThrowIfNull(fullSchema);
1011
ArgumentNullException.ThrowIfNull(propertyNamesInOrder);
1112

12-
var propertiesInOrder = new Dictionary<string, OpenApiSchema>();
13+
var propertiesInOrder = new Dictionary<string, IOpenApiSchema>();
1314

1415
foreach (var propertyName in propertyNamesInOrder)
1516
{
@@ -24,7 +25,7 @@ public static void ReorderProperties(this OpenApiSchema fullSchema, IEnumerable<
2425
fullSchema.Properties = propertiesInOrder;
2526
}
2627

27-
public static OpenApiSchema WrapInExtendedSchema(this OpenApiSchema source)
28+
public static OpenApiSchema WrapInExtendedSchema(this IOpenApiSchema source)
2829
{
2930
ArgumentNullException.ThrowIfNull(source);
3031

@@ -34,11 +35,11 @@ public static OpenApiSchema WrapInExtendedSchema(this OpenApiSchema source)
3435
};
3536
}
3637

37-
public static OpenApiSchema UnwrapLastExtendedSchema(this OpenApiSchema source)
38+
public static IOpenApiSchema UnwrapLastExtendedSchema(this IOpenApiSchema source)
3839
{
3940
ArgumentNullException.ThrowIfNull(source);
4041

41-
if (source.AllOf is { Count: > 0 })
42+
if (sourceisOpenApiSchema&&source.AllOf is { Count: > 0 })
4243
{
4344
return source.AllOf.Last();
4445
}

‎src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/AtomicOperationCodeSchemaGenerator.cs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using JsonApiDotNetCore.Serialization.Objects;
22
using Microsoft.OpenApi.Any;
33
using Microsoft.OpenApi.Models;
4+
using Microsoft.OpenApi.Models.References;
45
using Swashbuckle.AspNetCore.SwaggerGen;
56

67
namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components;
@@ -19,22 +20,15 @@ public AtomicOperationCodeSchemaGenerator(SchemaGenerationTracer schemaGeneratio
1920
_schemaIdSelector = schemaIdSelector;
2021
}
2122

22-
public OpenApiSchema GenerateSchema(AtomicOperationCode operationCode, SchemaRepository schemaRepository)
23+
public OpenApiSchemaReference GenerateSchema(AtomicOperationCode operationCode, SchemaRepository schemaRepository)
2324
{
2425
ArgumentNullException.ThrowIfNull(schemaRepository);
2526

2627
var schemaId = _schemaIdSelector.GetAtomicOperationCodeSchemaId(operationCode);
2728

2829
if (schemaRepository.Schemas.ContainsKey(schemaId))
2930
{
30-
return new OpenApiSchema
31-
{
32-
Reference = new OpenApiReference
33-
{
34-
Id = schemaId,
35-
Type = ReferenceType.Schema
36-
}
37-
};
31+
return new OpenApiSchemaReference(schemaId);
3832
}
3933

4034
using var traceScope = _schemaGenerationTracer.TraceStart(this, operationCode);
@@ -43,8 +37,8 @@ public OpenApiSchema GenerateSchema(AtomicOperationCode operationCode, SchemaRep
4337

4438
var fullSchema = new OpenApiSchema
4539
{
46-
Type = "string",
47-
Enum = [newOpenApiString(enumValue)]
40+
Type = JsonSchemaType.String,
41+
Enum = [enumValue]
4842
};
4943

5044
var referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema);

‎src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataContainerSchemaGenerator.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects;
44
using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents;
55
using Microsoft.OpenApi.Models;
6+
using Microsoft.OpenApi.Models.References;
67
using Swashbuckle.AspNetCore.SwaggerGen;
78

89
namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components;
@@ -27,14 +28,14 @@ public DataContainerSchemaGenerator(SchemaGenerationTracer schemaGenerationTrace
2728
_resourceGraph = resourceGraph;
2829
}
2930

30-
public OpenApiSchema GenerateSchemaForCommonResourceDataInResponse(SchemaRepository schemaRepository)
31+
public OpenApiSchemaReference GenerateSchemaForCommonResourceDataInResponse(SchemaRepository schemaRepository)
3132
{
3233
ArgumentNullException.ThrowIfNull(schemaRepository);
3334

3435
return _dataSchemaGenerator.GenerateSchemaForCommonData(typeof(ResourceInResponse), schemaRepository);
3536
}
3637

37-
public OpenApiSchema GenerateSchema(Type dataContainerSchemaType, ResourceType resourceType, bool forRequestSchema, bool canIncludeRelated,
38+
public OpenApiSchemaReference GenerateSchema(Type dataContainerSchemaType, ResourceType resourceType, bool forRequestSchema, bool canIncludeRelated,
3839
SchemaRepository schemaRepository)
3940
{
4041
ArgumentNullException.ThrowIfNull(dataContainerSchemaType);

‎src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataSchemaGenerator.cs

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
using System.Collections.Concurrent;
22
using System.Reflection;
33
using System.Runtime.CompilerServices;
4+
using System.Text.Json;
5+
using System.Text.Json.Nodes;
46
using JsonApiDotNetCore.Configuration;
57
using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata;
68
using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects;
79
using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents;
810
using Microsoft.OpenApi.Any;
911
using Microsoft.OpenApi.Models;
12+
using Microsoft.OpenApi.Models.Interfaces;
13+
using Microsoft.OpenApi.Models.References;
1014
using Swashbuckle.AspNetCore.SwaggerGen;
1115

1216
namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components;
@@ -79,7 +83,7 @@ public DataSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, Schema
7983
_resourceDocumentationReader = resourceDocumentationReader;
8084
}
8185

82-
public OpenApiSchema GenerateSchema(Type dataSchemaType, bool forRequestSchema, SchemaRepository schemaRepository)
86+
public OpenApiSchemaReference GenerateSchema(Type dataSchemaType, bool forRequestSchema, SchemaRepository schemaRepository)
8387
{
8488
// For a given resource (identifier) type, we always generate the full type hierarchy. Discriminator mappings
8589
// are managed manually, because there's no way to intercept in the Swashbuckle recursive component schema generation.
@@ -114,11 +118,11 @@ public OpenApiSchema GenerateSchema(Type dataSchemaType, bool forRequestSchema,
114118

115119
using var traceScope = _schemaGenerationTracer.TraceStart(this, dataSchemaType);
116120

117-
referenceSchemaForData = _defaultSchemaGenerator.GenerateSchema(dataSchemaType, schemaRepository);
118-
var fullSchemaForData = schemaRepository.Schemas[referenceSchemaForData.Reference.Id];
121+
referenceSchemaForData = (OpenApiSchemaReference)_defaultSchemaGenerator.GenerateSchema(dataSchemaType, schemaRepository);
122+
var fullSchemaForData = (OpenApiSchema)schemaRepository.Schemas[referenceSchemaForData.Reference.Id];
119123
fullSchemaForData.AdditionalPropertiesAllowed = false;
120124

121-
var inlineSchemaForData = fullSchemaForData.UnwrapLastExtendedSchema();
125+
var inlineSchemaForData = (OpenApiSchema)fullSchemaForData.UnwrapLastExtendedSchema();
122126

123127
SetAbstract(inlineSchemaForData, resourceSchemaType);
124128
SetResourceType(inlineSchemaForData, resourceType, schemaRepository);
@@ -142,7 +146,7 @@ public OpenApiSchema GenerateSchema(Type dataSchemaType, bool forRequestSchema,
142146

143147
if (RequiresRootObjectTypeInDataSchema(resourceSchemaType, forRequestSchema))
144148
{
145-
fullSchemaForData.Extensions[SetSchemaTypeToObjectDocumentFilter.RequiresRootObjectTypeKey] = new OpenApiBoolean(true);
149+
fullSchemaForData.Extensions[SetSchemaTypeToObjectDocumentFilter.RequiresRootObjectTypeKey] = new OpenApiAny(true);
146150
}
147151

148152
traceScope.TraceSucceeded(referenceSchemaForData.Reference.Id);
@@ -202,7 +206,7 @@ public OpenApiSchema GenerateSchema(Type dataSchemaType, bool forRequestSchema,
202206
return boxedSchemaType.Value;
203207
}
204208

205-
public OpenApiSchema GenerateSchemaForCommonData(Type commonDataSchemaType, SchemaRepository schemaRepository)
209+
public OpenApiSchemaReference GenerateSchemaForCommonData(Type commonDataSchemaType, SchemaRepository schemaRepository)
206210
{
207211
ArgumentNullException.ThrowIfNull(commonDataSchemaType);
208212
ArgumentNullException.ThrowIfNull(schemaRepository);
@@ -219,9 +223,9 @@ public OpenApiSchema GenerateSchemaForCommonData(Type commonDataSchemaType, Sche
219223

220224
var fullSchema = new OpenApiSchema
221225
{
222-
Type = "object",
226+
Type = JsonSchemaType.Object,
223227
Required = new SortedSet<string>([JsonApiPropertyName.Type]),
224-
Properties = new Dictionary<string, OpenApiSchema>
228+
Properties = new Dictionary<string, IOpenApiSchema>
225229
{
226230
[JsonApiPropertyName.Type] = referenceSchemaForResourceType.WrapInExtendedSchema(),
227231
[referenceSchemaForMeta.Reference.Id] = referenceSchemaForMeta.WrapInExtendedSchema()
@@ -234,7 +238,7 @@ public OpenApiSchema GenerateSchemaForCommonData(Type commonDataSchemaType, Sche
234238
},
235239
Extensions =
236240
{
237-
["x-abstract"] = new OpenApiBoolean(true)
241+
["x-abstract"] = new OpenApiAny(true)
238242
}
239243
};
240244

@@ -272,7 +276,7 @@ private static void SetAbstract(OpenApiSchema fullSchema, ResourceSchemaType res
272276
{
273277
if (resourceSchemaType.ResourceType.ClrType.IsAbstract && resourceSchemaType.SchemaOpenType != typeof(IdentifierInRequest<>))
274278
{
275-
fullSchema.Extensions["x-abstract"] = new OpenApiBoolean(true);
279+
fullSchema.Extensions["x-abstract"] = new OpenApiAny(true);
276280
}
277281
}
278282

@@ -367,8 +371,8 @@ private void SetFieldSchemaMembers(OpenApiSchema fullSchemaForData, ResourceSche
367371
{
368372
var propertyNameInSchema = forAttributes ? JsonApiPropertyName.Attributes : JsonApiPropertyName.Relationships;
369373

370-
var referenceSchemaForFields = fullSchemaForData.Properties[propertyNameInSchema].UnwrapLastExtendedSchema();
371-
var fullSchemaForFields = schemaRepository.Schemas[referenceSchemaForFields.Reference.Id];
374+
var referenceSchemaForFields = (OpenApiSchemaReference)fullSchemaForData.Properties[propertyNameInSchema].UnwrapLastExtendedSchema();
375+
var fullSchemaForFields = (OpenApiSchema)schemaRepository.Schemas[referenceSchemaForFields.Reference.Id];
372376
fullSchemaForFields.AdditionalPropertiesAllowed = false;
373377

374378
SetAbstract(fullSchemaForFields, resourceSchemaTypeForData);
@@ -437,7 +441,7 @@ private ResourceSchemaType GetResourceSchemaTypeForFieldsProperty(ResourceSchema
437441
return ResourceSchemaType.Create(fieldsConstructedType, _resourceGraph);
438442
}
439443

440-
private OpenApiSchema GenerateSchemaForCommonFields(Type commonFieldsSchemaType, SchemaRepository schemaRepository)
444+
private OpenApiSchemaReference GenerateSchemaForCommonFields(Type commonFieldsSchemaType, SchemaRepository schemaRepository)
441445
{
442446
if (schemaRepository.TryLookupByType(commonFieldsSchemaType, out var referenceSchema))
443447
{
@@ -450,9 +454,9 @@ private OpenApiSchema GenerateSchemaForCommonFields(Type commonFieldsSchemaType,
450454

451455
var fullSchema = new OpenApiSchema
452456
{
453-
Type = "object",
457+
Type = JsonSchemaType.Object,
454458
Required = new SortedSet<string>([OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName]),
455-
Properties = new Dictionary<string, OpenApiSchema>
459+
Properties = new Dictionary<string, IOpenApiSchema>
456460
{
457461
[OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName] = referenceSchemaForResourceType.WrapInExtendedSchema()
458462
},
@@ -464,7 +468,7 @@ private OpenApiSchema GenerateSchemaForCommonFields(Type commonFieldsSchemaType,
464468
},
465469
Extensions =
466470
{
467-
["x-abstract"] = new OpenApiBoolean(true)
471+
["x-abstract"] = new OpenApiAny(true)
468472
}
469473
};
470474

@@ -489,7 +493,7 @@ private void MapInDiscriminator(ResourceSchemaType resourceSchemaType, bool forR
489493
: resourceSchemaType.ChangeResourceType(baseResourceType).SchemaConstructedType;
490494

491495
var referenceSchemaForBase = schemaRepository.LookupByType(baseSchemaType);
492-
var inlineSchemaForBase = schemaRepository.Schemas[referenceSchemaForBase.Reference.Id].UnwrapLastExtendedSchema();
496+
var inlineSchemaForBase = (OpenApiSchema)schemaRepository.Schemas[referenceSchemaForBase.Reference.Id].UnwrapLastExtendedSchema();
493497

494498
inlineSchemaForBase.Discriminator ??= new OpenApiDiscriminator
495499
{
@@ -545,9 +549,9 @@ private void MapResourceTypeInEnum(string publicName, SchemaRepository schemaRep
545549
var schemaId = _schemaIdSelector.GetResourceTypeSchemaId(null);
546550
var fullSchema = schemaRepository.Schemas[schemaId];
547551

548-
if (!fullSchema.Enum.Any(openApiAny => openApiAny is OpenApiString openApiString && openApiString.Value == publicName))
552+
if (!fullSchema.Enum.Any(openApiAny => openApiAny is JsonValue openApiString && openApiString.GetValueKind()==JsonValueKind.String&&openApiString.GetValue<string>() == publicName))
549553
{
550-
fullSchema.Enum.Add(newOpenApiString(publicName));
554+
fullSchema.Enum.Add(publicName);
551555
}
552556
}
553557

@@ -572,11 +576,11 @@ private void GenerateDataSchemasForDirectlyDerivedTypes(ResourceSchemaType resou
572576

573577
using var traceScope = _schemaGenerationTracer.TraceStart(this, resourceSchemaTypeForDerived.SchemaConstructedType);
574578

575-
var referenceSchemaForDerived = _defaultSchemaGenerator.GenerateSchema(derivedSchemaType, schemaRepository);
576-
var fullSchemaForDerived = schemaRepository.Schemas[referenceSchemaForDerived.Reference.Id];
579+
var referenceSchemaForDerived = (OpenApiSchemaReference)_defaultSchemaGenerator.GenerateSchema(derivedSchemaType, schemaRepository);
580+
var fullSchemaForDerived = (OpenApiSchema)schemaRepository.Schemas[referenceSchemaForDerived.Reference.Id];
577581
fullSchemaForDerived.AdditionalPropertiesAllowed = false;
578582

579-
var inlineSchemaForDerived = fullSchemaForDerived.UnwrapLastExtendedSchema();
583+
var inlineSchemaForDerived = (OpenApiSchema)fullSchemaForDerived.UnwrapLastExtendedSchema();
580584
SetResourceFields(inlineSchemaForDerived, resourceSchemaTypeForDerived, forRequestSchema, schemaRepository);
581585

582586
SetAbstract(inlineSchemaForDerived, resourceSchemaTypeForDerived);
@@ -605,7 +609,7 @@ private void GenerateDataSchemasForDirectlyDerivedTypes(ResourceSchemaType resou
605609
if (RequiresRootObjectTypeInDataSchema(resourceSchemaTypeForDerived, forRequestSchema))
606610
{
607611
var fullSchemaForData = schemaRepository.Schemas[referenceSchemaForDerived.Reference.Id];
608-
fullSchemaForData.Extensions[SetSchemaTypeToObjectDocumentFilter.RequiresRootObjectTypeKey] = new OpenApiBoolean(true);
612+
fullSchemaForData.Extensions[SetSchemaTypeToObjectDocumentFilter.RequiresRootObjectTypeKey] = new OpenApiAny(true);
609613
}
610614

611615
GenerateDataSchemasForDirectlyDerivedTypes(resourceSchemaTypeForDerived, forRequestSchema, schemaRepository);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /