Skip to content

Commit 3e01136

Browse files
authored
OpenAPI: Generalization of naming conventions (#1123)
* Fix failing test when run in parallel, respect naming convention as set in SerializerSettings for properties in swagger doc * Add client and swagger doc tests fixup2 * Added annotations to JsonApiObject types * Added tests for pascal and camelcase and introduced fixes to make them work. * Fix CI - Fixed hanging CI by adding xunit.runner.json - Moved retrieval of swagger document to test context fixture * Process review feedback * ignore generated swagger.json files * Restore formatting in csproj files * Additional self-review round * remove BeJson overload * Merge base test suite and text context, move swagger.json to swagger.g.json in client test project * Process feedback * Process feedback * cleanup code * Fix irregularities in test file
1 parent fa28605 commit 3e01136

File tree

66 files changed

+10330
-217
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+10330
-217
lines changed

Diff for: JsonApiDotNetCore.sln.DotSettings

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ JsonApiDotNetCore.ArgumentGuard.NotNull($EXPR$, $NAME$);</s:String>
1515
<s:Int64 x:Key="/Default/CodeEditing/NullCheckPatterns/PatternTypeNamesToPriority/=JetBrains_002EReSharper_002EFeature_002EServices_002ECSharp_002ENullChecking_002ETraceAssertPattern/@EntryIndexedValue">50</s:Int64>
1616
<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/PropagateAnnotations/@EntryValue">False</s:Boolean>
1717
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=swagger_002Ejson/@EntryIndexedValue">True</s:Boolean>
18+
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=swagger_002Eg_002Ejson/@EntryIndexedValue">swagger.g.json</s:String>
19+
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=swagger_002Ejson/@EntryIndexedValue">swagger.json</s:String>
1820
<s:String x:Key="/Default/CodeInspection/Highlighting/AnalysisEnabled/@EntryValue">SOLUTION</s:String>
1921
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/IdentifierHighlightingEnabled/@EntryValue">True</s:Boolean>
2022
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/IncludeWarningsInSwea/@EntryValue">True</s:Boolean>

Diff for: src/JsonApiDotNetCore.OpenApi.Client/ApiException.cs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using JetBrains.Annotations;
2+
3+
// We cannot rely on generating ApiException as soon as we are generating multiple clients, see https://github.com/RicoSuter/NSwag/issues/2839#issuecomment-776647377.
4+
// Instead, we configure NSwag to point to the exception below in the generated code.
5+
6+
// ReSharper disable once CheckNamespace
7+
namespace JsonApiDotNetCore.OpenApi.Client.Exceptions;
8+
9+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
10+
public sealed class ApiException : Exception
11+
{
12+
public int StatusCode { get; }
13+
14+
public string? Response { get; }
15+
16+
public IReadOnlyDictionary<string, IEnumerable<string>> Headers { get; }
17+
18+
public ApiException(string message, int statusCode, string? response, IReadOnlyDictionary<string, IEnumerable<string>> headers, Exception innerException)
19+
: base($"{message}\n\nStatus: {statusCode}\nResponse: \n{response ?? "(null)"}", innerException)
20+
{
21+
StatusCode = statusCode;
22+
Response = response;
23+
Headers = headers;
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
45
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
56
using JsonApiDotNetCore.Resources;
67

78
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
89

10+
// Types in the current namespace are never touched by ASP.NET ModelState validation, therefore using a non-nullable reference type for a property does not
11+
// imply this property is required. Instead, we use [Required] explicitly, because this is how Swashbuckle is instructed to mark properties as required.
912
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
1013
internal sealed class NullableResourceIdentifierResponseDocument<TResource> : NullableSingleData<ResourceIdentifierObject<TResource>>
1114
where TResource : IIdentifiable
1215
{
16+
[JsonPropertyName("meta")]
1317
public IDictionary<string, object> Meta { get; set; } = null!;
1418

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

1722
[Required]
23+
[JsonPropertyName("links")]
1824
public LinksInResourceIdentifierDocument Links { get; set; } = null!;
1925
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/NullableSecondaryResourceResponseDocument.cs

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
45
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
@@ -10,10 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
1011
internal sealed class NullableSecondaryResourceResponseDocument<TResource> : NullableSingleData<ResourceObjectInResponse<TResource>>
1112
where TResource : IIdentifiable
1213
{
14+
[JsonPropertyName("meta")]
1315
public IDictionary<string, object> Meta { get; set; } = null!;
1416

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

1720
[Required]
21+
[JsonPropertyName("links")]
1822
public LinksInResourceDocument Links { get; set; } = null!;
1923
}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
45
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
56
using JsonApiDotNetCore.Resources;
67

78
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
89

9-
// Types in the current namespace are never touched by ASP.NET ModelState validation, therefore using a non-nullable reference type for a property does not
10-
// imply this property is required. Instead, we use [Required] explicitly, because this is how Swashbuckle is instructed to mark properties as required.
1110
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
1211
internal sealed class PrimaryResourceResponseDocument<TResource> : SingleData<ResourceObjectInResponse<TResource>>
1312
where TResource : IIdentifiable
1413
{
14+
[JsonPropertyName("meta")]
1515
public IDictionary<string, object> Meta { get; set; } = null!;
1616

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

1920
[Required]
21+
[JsonPropertyName("links")]
2022
public LinksInResourceDocument Links { get; set; } = null!;
2123
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/ResourceCollectionResponseDocument.cs

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
45
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
@@ -10,10 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
1011
internal sealed class ResourceCollectionResponseDocument<TResource> : ManyData<ResourceObjectInResponse<TResource>>
1112
where TResource : IIdentifiable
1213
{
14+
[JsonPropertyName("meta")]
1315
public IDictionary<string, object> Meta { get; set; } = null!;
1416

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

1720
[Required]
21+
[JsonPropertyName("links")]
1822
public LinksInResourceCollectionDocument Links { get; set; } = null!;
1923
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/ResourceIdentifierCollectionResponseDocument.cs

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
45
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
@@ -10,10 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
1011
internal sealed class ResourceIdentifierCollectionResponseDocument<TResource> : ManyData<ResourceIdentifierObject<TResource>>
1112
where TResource : IIdentifiable
1213
{
14+
[JsonPropertyName("meta")]
1315
public IDictionary<string, object> Meta { get; set; } = null!;
1416

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

1720
[Required]
21+
[JsonPropertyName("links")]
1822
public LinksInResourceIdentifierCollectionDocument Links { get; set; } = null!;
1923
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/ResourceIdentifierResponseDocument.cs

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
45
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
@@ -10,10 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
1011
internal sealed class ResourceIdentifierResponseDocument<TResource> : SingleData<ResourceIdentifierObject<TResource>>
1112
where TResource : IIdentifiable
1213
{
14+
[JsonPropertyName("meta")]
1315
public IDictionary<string, object> Meta { get; set; } = null!;
1416

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

1720
[Required]
21+
[JsonPropertyName("links")]
1822
public LinksInResourceIdentifierDocument Links { get; set; } = null!;
1923
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Documents/SecondaryResourceResponseDocument.cs

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
45
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
@@ -10,10 +11,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Documents;
1011
internal sealed class SecondaryResourceResponseDocument<TResource> : SingleData<ResourceObjectInResponse<TResource>>
1112
where TResource : IIdentifiable
1213
{
14+
[JsonPropertyName("meta")]
1315
public IDictionary<string, object> Meta { get; set; } = null!;
1416

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

1720
[Required]
21+
[JsonPropertyName("links")]
1822
public LinksInResourceDocument Links { get; set; } = null!;
1923
}
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1+
using System.Text.Json.Serialization;
12
using JetBrains.Annotations;
23

34
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects;
45

56
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
67
internal sealed class JsonapiObject
78
{
9+
[JsonPropertyName("version")]
810
public string Version { get; set; } = null!;
911

12+
[JsonPropertyName("ext")]
1013
public ICollection<string> Ext { get; set; } = null!;
1114

15+
[JsonPropertyName("profile")]
1216
public ICollection<string> Profile { get; set; } = null!;
1317

18+
[JsonPropertyName("meta")]
1419
public IDictionary<string, object> Meta { get; set; } = null!;
1520
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Links/LinksInRelationshipObject.cs

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34

45
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
@@ -7,8 +8,10 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
78
internal sealed class LinksInRelationshipObject
89
{
910
[Required]
11+
[JsonPropertyName("self")]
1012
public string Self { get; set; } = null!;
1113

1214
[Required]
15+
[JsonPropertyName("related")]
1316
public string Related { get; set; } = null!;
1417
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Links/LinksInResourceCollectionDocument.cs

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34

45
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
@@ -7,16 +8,22 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
78
internal sealed class LinksInResourceCollectionDocument
89
{
910
[Required]
11+
[JsonPropertyName("self")]
1012
public string Self { get; set; } = null!;
1113

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

1417
[Required]
18+
[JsonPropertyName("first")]
1519
public string First { get; set; } = null!;
1620

21+
[JsonPropertyName("last")]
1722
public string Last { get; set; } = null!;
1823

24+
[JsonPropertyName("prev")]
1925
public string Prev { get; set; } = null!;
2026

27+
[JsonPropertyName("next")]
2128
public string Next { get; set; } = null!;
2229
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Links/LinksInResourceDocument.cs

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34

45
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
@@ -7,7 +8,9 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
78
internal sealed class LinksInResourceDocument
89
{
910
[Required]
11+
[JsonPropertyName("self")]
1012
public string Self { get; set; } = null!;
1113

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

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Links/LinksInResourceIdentifierCollectionDocument.cs

+8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34

45
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
@@ -7,19 +8,26 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
78
internal sealed class LinksInResourceIdentifierCollectionDocument
89
{
910
[Required]
11+
[JsonPropertyName("self")]
1012
public string Self { get; set; } = null!;
1113

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

1417
[Required]
18+
[JsonPropertyName("related")]
1519
public string Related { get; set; } = null!;
1620

1721
[Required]
22+
[JsonPropertyName("first")]
1823
public string First { get; set; } = null!;
1924

25+
[JsonPropertyName("last")]
2026
public string Last { get; set; } = null!;
2127

28+
[JsonPropertyName("prev")]
2229
public string Prev { get; set; } = null!;
2330

31+
[JsonPropertyName("next")]
2432
public string Next { get; set; } = null!;
2533
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Links/LinksInResourceIdentifierDocument.cs

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34

45
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
@@ -7,10 +8,13 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
78
internal sealed class LinksInResourceIdentifierDocument
89
{
910
[Required]
11+
[JsonPropertyName("self")]
1012
public string Self { get; set; } = null!;
1113

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

1417
[Required]
18+
[JsonPropertyName("related")]
1519
public string Related { get; set; } = null!;
1620
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Links/LinksInResourceObject.cs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34

45
namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
@@ -7,5 +8,6 @@ namespace JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
78
internal sealed class LinksInResourceObject
89
{
910
[Required]
11+
[JsonPropertyName("self")]
1012
public string Self { get; set; } = null!;
1113
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/ManyData.cs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
45

@@ -9,5 +10,6 @@ internal abstract class ManyData<TData>
910
where TData : ResourceIdentifierObject
1011
{
1112
[Required]
13+
[JsonPropertyName("data")]
1214
public ICollection<TData> Data { get; set; } = null!;
1315
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/NullableSingleData.cs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
45

@@ -9,5 +10,6 @@ internal abstract class NullableSingleData<TData>
910
where TData : ResourceIdentifierObject
1011
{
1112
[Required]
13+
[JsonPropertyName("data")]
1214
public TData? Data { get; set; }
1315
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Relationships/NullableToOneRelationshipInResponse.cs

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
45
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
@@ -11,7 +12,9 @@ internal sealed class NullableToOneRelationshipInResponse<TResource> : NullableS
1112
where TResource : IIdentifiable
1213
{
1314
[Required]
15+
[JsonPropertyName("links")]
1416
public LinksInRelationshipObject Links { get; set; } = null!;
1517

18+
[JsonPropertyName("meta")]
1619
public IDictionary<string, object> Meta { get; set; } = null!;
1720
}

Diff for: src/JsonApiDotNetCore.OpenApi/JsonApiObjects/Relationships/ToManyRelationshipInResponse.cs

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using System.Text.Json.Serialization;
23
using JetBrains.Annotations;
34
using JsonApiDotNetCore.OpenApi.JsonApiObjects.Links;
45
using JsonApiDotNetCore.OpenApi.JsonApiObjects.ResourceObjects;
@@ -11,7 +12,9 @@ internal sealed class ToManyRelationshipInResponse<TResource> : ManyData<Resourc
1112
where TResource : IIdentifiable
1213
{
1314
[Required]
15+
[JsonPropertyName("links")]
1416
public LinksInRelationshipObject Links { get; set; } = null!;
1517

18+
[JsonPropertyName("meta")]
1619
public IDictionary<string, object> Meta { get; set; } = null!;
1720
}

0 commit comments

Comments
 (0)