Skip to content

Correct order of JSON:API members in generated swagger.json #1362

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions src/JsonApiDotNetCore.OpenApi/JsonApiObjectPropertyName.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
internal sealed class NullableResourceIdentifierResponseDocument<TResource> : NullableSingleData<ResourceIdentifierObject<TResource>>
where TResource : IIdentifiable
{
[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;

[JsonPropertyName("jsonapi")]
public JsonapiObject Jsonapi { get; set; } = null!;

[Required]
[JsonPropertyName("links")]
public LinksInResourceIdentifierDocument Links { get; set; } = null!;

[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
internal sealed class NullableSecondaryResourceResponseDocument<TResource> : NullableSingleData<ResourceObjectInResponse<TResource>>
where TResource : IIdentifiable
{
[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;

[JsonPropertyName("jsonapi")]
public JsonapiObject Jsonapi { get; set; } = null!;

[Required]
[JsonPropertyName("links")]
public LinksInResourceDocument Links { get; set; } = null!;

[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
internal sealed class PrimaryResourceResponseDocument<TResource> : SingleData<ResourceObjectInResponse<TResource>>
where TResource : IIdentifiable
{
[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;

[JsonPropertyName("jsonapi")]
public JsonapiObject Jsonapi { get; set; } = null!;

[Required]
[JsonPropertyName("links")]
public LinksInResourceDocument Links { get; set; } = null!;

[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
internal sealed class ResourceCollectionResponseDocument<TResource> : ManyData<ResourceObjectInResponse<TResource>>
where TResource : IIdentifiable
{
[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;

[JsonPropertyName("jsonapi")]
public JsonapiObject Jsonapi { get; set; } = null!;

[Required]
[JsonPropertyName("links")]
public LinksInResourceCollectionDocument Links { get; set; } = null!;

[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
internal sealed class ResourceIdentifierCollectionResponseDocument<TResource> : ManyData<ResourceIdentifierObject<TResource>>
where TResource : IIdentifiable
{
[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;

[JsonPropertyName("jsonapi")]
public JsonapiObject Jsonapi { get; set; } = null!;

[Required]
[JsonPropertyName("links")]
public LinksInResourceIdentifierCollectionDocument Links { get; set; } = null!;

[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
internal sealed class ResourceIdentifierResponseDocument<TResource> : SingleData<ResourceIdentifierObject<TResource>>
where TResource : IIdentifiable
{
[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;

[JsonPropertyName("jsonapi")]
public JsonapiObject Jsonapi { get; set; } = null!;

[Required]
[JsonPropertyName("links")]
public LinksInResourceIdentifierDocument Links { get; set; } = null!;

[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
internal sealed class SecondaryResourceResponseDocument<TResource> : SingleData<ResourceObjectInResponse<TResource>>
where TResource : IIdentifiable
{
[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;

[JsonPropertyName("jsonapi")]
public JsonapiObject Jsonapi { get; set; } = null!;

[Required]
[JsonPropertyName("links")]
public LinksInResourceDocument Links { get; set; } = null!;

[JsonPropertyName("meta")]
public IDictionary<string, object> Meta { get; set; } = null!;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ internal sealed class LinksInResourceIdentifierCollectionDocument
[JsonPropertyName("self")]
public string Self { get; set; } = null!;

[JsonPropertyName("describedby")]
public string Describedby { get; set; } = null!;

[Required]
[JsonPropertyName("related")]
public string Related { get; set; } = null!;

[JsonPropertyName("describedby")]
public string Describedby { get; set; } = null!;

[Required]
[JsonPropertyName("first")]
public string First { get; set; } = null!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ internal sealed class LinksInResourceIdentifierDocument
[JsonPropertyName("self")]
public string Self { get; set; } = null!;

[JsonPropertyName("describedby")]
public string Describedby { get; set; } = null!;

[Required]
[JsonPropertyName("related")]
public string Related { get; set; } = null!;

[JsonPropertyName("describedby")]
public string Describedby { get; set; } = null!;
}
17 changes: 17 additions & 0 deletions src/JsonApiDotNetCore.OpenApi/JsonApiPropertyName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma warning disable AV1008 // Class should not be static

namespace JsonApiDotNetCore.OpenApi;

internal static class JsonApiPropertyName
{
public const string Jsonapi = "jsonapi";
public const string Links = "links";
public const string Data = "data";
public const string Type = "type";
public const string Id = "id";
public const string Attributes = "attributes";
public const string Relationships = "relationships";
public const string Errors = "errors";
public const string Included = "included";
public const string Meta = "meta";
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ internal sealed class JsonApiSchemaGenerator : ISchemaGenerator
typeof(NullableToOneRelationshipInRequest<>)
};

private static readonly string[] DocumentPropertyNamesInOrder =
{
JsonApiPropertyName.Jsonapi,
JsonApiPropertyName.Links,
JsonApiPropertyName.Data,
JsonApiPropertyName.Errors,
JsonApiPropertyName.Included,
JsonApiPropertyName.Meta
};

private readonly ISchemaGenerator _defaultSchemaGenerator;
private readonly ResourceObjectSchemaGenerator _resourceObjectSchemaGenerator;
private readonly NullableReferenceSchemaGenerator _nullableReferenceSchemaGenerator;
Expand Down Expand Up @@ -76,7 +86,7 @@ public OpenApiSchema GenerateSchema(Type modelType, SchemaRepository schemaRepos
}
}

return _defaultSchemaGenerator.GenerateSchema(modelType, schemaRepository, memberInfo, parameterInfo);
return _defaultSchemaGenerator.GenerateSchema(modelType, schemaRepository, memberInfo, parameterInfo, routeInfo);
}

private static bool IsJsonApiDocument(Type type)
Expand All @@ -100,7 +110,9 @@ private OpenApiSchema GenerateJsonApiDocumentSchema(Type documentType)
? CreateArrayTypeDataSchema(referenceSchemaForResourceObject)
: referenceSchemaForResourceObject;

fullSchemaForDocument.Properties[JsonApiObjectPropertyName.Data] = referenceSchemaForDataObject;
fullSchemaForDocument.Properties[JsonApiPropertyName.Data] = referenceSchemaForDataObject;

fullSchemaForDocument.ReorderProperties(DocumentPropertyNamesInOrder);

return referenceSchemaForDocument;
}
Expand All @@ -120,8 +132,8 @@ private static bool IsDataPropertyNullableInDocument(Type documentType)
private void SetDataObjectSchemaToNullable(OpenApiSchema referenceSchemaForDocument)
{
OpenApiSchema fullSchemaForDocument = _schemaRepositoryAccessor.Current.Schemas[referenceSchemaForDocument.Reference.Id];
OpenApiSchema referenceSchemaForData = fullSchemaForDocument.Properties[JsonApiObjectPropertyName.Data];
fullSchemaForDocument.Properties[JsonApiObjectPropertyName.Data] = _nullableReferenceSchemaGenerator.GenerateSchema(referenceSchemaForData);
OpenApiSchema referenceSchemaForData = fullSchemaForDocument.Properties[JsonApiPropertyName.Data];
fullSchemaForDocument.Properties[JsonApiPropertyName.Data] = _nullableReferenceSchemaGenerator.GenerateSchema(referenceSchemaForData);
}

private static OpenApiSchema CreateArrayTypeDataSchema(OpenApiSchema referenceSchemaForResourceObject)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Microsoft.OpenApi.Models;

namespace JsonApiDotNetCore.OpenApi.SwaggerComponents;

internal static class OpenApiSchemaExtensions
{
public static void ReorderProperties(this OpenApiSchema fullSchemaForResourceObject, IEnumerable<string> propertyNamesInOrder)
{
var propertiesInOrder = new Dictionary<string, OpenApiSchema>();

foreach (string propertyName in propertyNamesInOrder)
{
if (fullSchemaForResourceObject.Properties.TryGetValue(propertyName, out OpenApiSchema? schema))
{
propertiesInOrder.Add(propertyName, schema);
}
}

if (fullSchemaForResourceObject.Properties.Count != propertiesInOrder.Count)
{
throw new UnreachableCodeException();
}

fullSchemaForResourceObject.Properties = propertiesInOrder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ internal sealed class ResourceFieldObjectSchemaBuilder
typeof(NullableToOneRelationshipInResponse<>)
};

private static readonly string[] RelationshipObjectPropertyNamesInOrder =
{
JsonApiPropertyName.Links,
JsonApiPropertyName.Data,
JsonApiPropertyName.Meta
};

private readonly ResourceTypeInfo _resourceTypeInfo;
private readonly ISchemaRepositoryAccessor _schemaRepositoryAccessor;
private readonly SchemaGenerator _defaultSchemaGenerator;
Expand Down Expand Up @@ -156,7 +163,7 @@ private void GenerateResourceIdentifierObjectSchema(Type resourceIdentifierObjec
_schemaRepositoryAccessor.Current.Schemas[referenceSchemaForResourceIdentifierObject.Reference.Id];

Type resourceType = resourceIdentifierObjectType.GetGenericArguments()[0];
fullSchemaForResourceIdentifierObject.Properties[JsonApiObjectPropertyName.Type] = _resourceTypeSchemaGenerator.Get(resourceType);
fullSchemaForResourceIdentifierObject.Properties[JsonApiPropertyName.Type] = _resourceTypeSchemaGenerator.Get(resourceType);
}

private void AddRelationshipSchemaToResourceObject(RelationshipAttribute relationship, OpenApiSchema fullSchemaForRelationshipsObject)
Expand Down Expand Up @@ -194,13 +201,14 @@ private OpenApiSchema CreateRelationshipSchema(Type relationshipSchemaType)

if (IsDataPropertyNullableInRelationshipSchemaType(relationshipSchemaType))
{
fullSchema.Properties[JsonApiObjectPropertyName.Data] =
_nullableReferenceSchemaGenerator.GenerateSchema(fullSchema.Properties[JsonApiObjectPropertyName.Data]);
fullSchema.Properties[JsonApiPropertyName.Data] = _nullableReferenceSchemaGenerator.GenerateSchema(fullSchema.Properties[JsonApiPropertyName.Data]);
}

if (IsRelationshipInResponseType(relationshipSchemaType))
{
fullSchema.Required.Remove(JsonApiObjectPropertyName.Data);
fullSchema.Required.Remove(JsonApiPropertyName.Data);

fullSchema.ReorderProperties(RelationshipObjectPropertyNamesInOrder);
}

return referenceSchema;
Expand Down
Loading