Skip to content

Commit 2f1664c

Browse files
committed
Update serializers
1 parent d97a3ee commit 2f1664c

16 files changed

+328
-69
lines changed

src/OpenApi.Client.Cli/Commands/GenerateCommand.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using Microsoft.CodeAnalysis;
77
using OpenApi.Client.Cli.Settings;
88
using OpenApi.Client.SourceGenerators.Contracts;
9-
using OpenApi.Client.SourceGenerators.Genertion;
9+
using OpenApi.Client.SourceGenerators.Generation;
1010
using OpenApi.Client.SourceGenerators.Schema;
1111
using OpenApi.Client.SourceGenerators.Serialization;
1212

@@ -70,7 +70,15 @@ SerializationResultError serializationResultError in serializationResult.Errors
7070
serializationResult.Result
7171
);
7272

73-
ClientGenerator generator = new(contract);
73+
ClientGenerator generator =
74+
new(
75+
contract,
76+
settings.Serializer switch
77+
{
78+
JsonSerializerType.NewtonsoftJson => ClientGeneratorSerializer.NewtonsoftJson,
79+
_ => ClientGeneratorSerializer.SystemTextJson
80+
}
81+
);
7482
GenerationResult<string> generatorResult = generator.Generate();
7583

7684
if (generatorResult.HasErrors)
@@ -100,6 +108,8 @@ await File.WriteAllTextAsync(
100108
return -4;
101109
}
102110

111+
AnsiConsole.MarkupLine($"[green]Success: File was properly saved to {settings.Output}.[/]");
112+
103113
return 0;
104114
}
105115

src/OpenApi.Client.Cli/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"OpenApiClient.Cli [Test]": {
44
"commandName": "Project",
55
"workingDirectory": "$(ProjectDir)",
6-
"commandLineArgs": "generate ..\\..\\tests\\OpenApi.Client.SourceGenerators.Roslyn431.UnitTests\\OpenApis\\openapi-3.1.0.json --output bin\\OpenApiTest.cs"
6+
"commandLineArgs": "generate ..\\..\\tests\\OpenApi.Client.SourceGenerators.Roslyn431.UnitTests\\OpenApis\\openapi-3.0.1.extended.json --output bin\\UsersClient.cs --namespace Clients.Users --classname UsersClient"
77
}
88
}
99
}

src/OpenApi.Client.SourceGenerators/Contracts/OpenApiContractParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
using Microsoft.CodeAnalysis;
77
using OpenApi.Client.SourceGenerators.Converters;
8-
using OpenApi.Client.SourceGenerators.Genertion;
8+
using OpenApi.Client.SourceGenerators.Generation;
99
using OpenApi.Client.SourceGenerators.Schema;
1010

1111
namespace OpenApi.Client.SourceGenerators.Contracts;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// This Source Code Form is subject to the terms of the MIT License.
2+
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
3+
// Copyright (C) Leszek Pomianowski and OpenAPI Client Contributors.
4+
// All Rights Reserved.
5+
6+
using OpenApi.Client.SourceGenerators.Contracts;
7+
8+
namespace OpenApi.Client.SourceGenerators.Generation;
9+
10+
internal sealed partial class ClientGenerator
11+
{
12+
public const string AtttributesHeader = """
13+
/// <summary>Represents an attribute used to specify the name of a property as it appears in the OpenAPI document.</summary>
14+
[global::System.CodeDom.Compiler.GeneratedCode("OpenApiClient", "%VERSION%")]
15+
%ACCESS% sealed class OpenApiPropertyAttribute : global::System.Attribute
16+
{
17+
public OpenApiPropertyAttribute(string name)
18+
{
19+
Name = name;
20+
}
21+
22+
public string Name { get; }
23+
}
24+
25+
""";
26+
27+
public static void AppendAttributes(StringBuilder builder, OpenApiContract contract)
28+
{
29+
builder.AppendLine(AtttributesHeader);
30+
}
31+
}

src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Class.cs

Lines changed: 82 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,80 @@
55

66
using OpenApi.Client.SourceGenerators.Contracts;
77

8-
namespace OpenApi.Client.SourceGenerators.Genertion;
8+
namespace OpenApi.Client.SourceGenerators.Generation;
99

1010
internal sealed partial class ClientGenerator
1111
{
12-
public const string ClassHeader = """
12+
private const string SystemTextJsonClassHeader = """
1313
[global::System.CodeDom.Compiler.GeneratedCode("OpenApiClient", "%VERSION%")]
1414
%ACCESS% partial class %CLASS% : I%CLASS%
1515
{
1616
private global::System.Net.HttpStatusCode? lastStatusCode;
1717
18+
/// <summary>The JSON serializer used for the Open API Client.</summary>
19+
protected IOpenApiJsonSerializer serializer;
20+
1821
/// <summary>The HTTP Client used for the Open API Client.</summary>
19-
protected readonly global::System.Net.Http.HttpClient HttpClient;
22+
protected global::System.Net.Http.HttpClient HttpClient;
23+
24+
/// <summary>Initializes a new instance of the <see cref="OpenApiTest"/> class using the provided HttpClient. Uses a default instance of <see cref="IOpenApiJsonSerializer"/> for serialization.</summary>
25+
public %CLASS%(global::System.Net.Http.HttpClient httpClient)
26+
{
27+
HttpClient = httpClient;
28+
serializer = new OpenApiJsonSerializer();
29+
}
30+
31+
/// <summary>Initializes a new instance of the <see cref="OpenApiTest"/> class using the provided HttpClient and JsonSerializerOptions. Uses an instance of <see cref="IOpenApiJsonSerializer"/> configured with the provided <see cref="System.Text.Json.JsonSerializerOptions"/> for serialization.</summary>
32+
public %CLASS%(global::System.Net.Http.HttpClient httpClient, global::System.Text.Json.JsonSerializerOptions jsonSettings)
33+
{
34+
HttpClient = httpClient;
35+
serializer = new OpenApiJsonSerializer(jsonSettings);
36+
}
2037
21-
/// <summary>Options for the serializer used to create API objects.</summary>
22-
protected readonly global::System.Text.Json.JsonSerializerOptions JsonSettings;
38+
/// <summary>Initializes a new instance of the <see cref="OpenApiTest"/> class using the provided HttpClient and IOpenApiJsonSerializer.</summary>
39+
public %CLASS%(global::System.Net.Http.HttpClient httpClient, IOpenApiJsonSerializer serializer)
40+
{
41+
HttpClient = httpClient;
42+
serializer = serializer;
43+
}
44+
45+
""";
46+
47+
private const string NewtonsoftJsonClassHeader = """
48+
[global::System.CodeDom.Compiler.GeneratedCode("OpenApiClient", "%VERSION%")]
49+
%ACCESS% partial class %CLASS% : I%CLASS%
50+
{
51+
private global::System.Net.HttpStatusCode? lastStatusCode;
2352
53+
private OpenApiJsonSerializer serializer;
54+
55+
/// <summary>The HTTP Client used for the Open API Client.</summary>
56+
protected readonly global::System.Net.Http.HttpClient HttpClient;
57+
58+
/// <summary>Initializes a new instance of the <see cref="OpenApiTest"/> class using the provided HttpClient. Uses a default instance of <see cref="IOpenApiJsonSerializer"/> for serialization.</summary>
2459
public %CLASS%(global::System.Net.Http.HttpClient httpClient)
25-
: this(httpClient, new global::System.Text.Json.JsonSerializerOptions
26-
{
27-
PropertyNameCaseInsensitive = true,
28-
Converters =
29-
{
30-
new global::System.Text.Json.Serialization.JsonStringEnumConverter()
31-
}
32-
})
3360
{
61+
HttpClient = httpClient;
62+
serializer = new OpenApiJsonSerializer();
3463
}
3564
36-
protected %CLASS%() : this(default!, default!)
65+
/// <summary>Initializes a new instance of the <see cref="OpenApiTest"/> class using the provided HttpClient and JsonSerializerOptions. Uses an instance of <see cref="IOpenApiJsonSerializer"/> configured with the provided <see cref="Newtonsoft.Json.JsonSerializerSettings"/> for serialization.</summary>
66+
public %CLASS%(global::System.Net.Http.HttpClient httpClient, global::Newtonsoft.Json.JsonSerializerSettings jsonSettings)
3767
{
68+
HttpClient = httpClient;
69+
serializer = new OpenApiJsonSerializer(jsonSettings);
3870
}
3971
40-
protected %CLASS%(global::System.Net.Http.HttpClient httpClient, global::System.Text.Json.JsonSerializerOptions jsonSettings)
72+
/// <summary>Initializes a new instance of the <see cref="OpenApiTest"/> class using the provided HttpClient and IOpenApiJsonSerializer.</summary>
73+
public %CLASS%(global::System.Net.Http.HttpClient httpClient, IOpenApiJsonSerializer serializer)
4174
{
4275
HttpClient = httpClient;
43-
JsonSettings = jsonSettings;
76+
serializer = serializer;
4477
}
4578
4679
""";
4780

48-
public const string ClassFooter = """
81+
private const string ClassFooter = """
4982
/// <inheritdoc/>
5083
public virtual global::System.Net.HttpStatusCode? GetLastStatusCode()
5184
{
@@ -91,7 +124,7 @@ protected virtual void ResetStatusCode()
91124
return null;
92125
}
93126
94-
return global::System.Text.Json.JsonSerializer.Serialize(input, JsonSettings);
127+
return serializer.Serialize(input);
95128
}
96129
97130
/// <summary>Tries to serialize body returned by HTTP request.</summary>
@@ -102,7 +135,18 @@ protected virtual void ResetStatusCode()
102135
return default;
103136
}
104137
105-
return global::System.Text.Json.JsonSerializer.Deserialize<TResponse>(input, JsonSettings);
138+
return serializer.Deserialize<TResponse>(input);
139+
}
140+
141+
/// <summary>Computes path string for HTTP request.</summary>
142+
protected virtual string? ComputePath(string? path, params string[] parameters)
143+
{
144+
if (parameters.Length == 0)
145+
{
146+
return path;
147+
}
148+
149+
return string.Format(path, parameters);
106150
}
107151
108152
/// <summary>Computes query string for HTTP request.</summary>
@@ -127,7 +171,10 @@ protected virtual void ResetStatusCode()
127171
queryString.Append("&");
128172
}
129173
130-
queryString.Append(global::System.Uri.EscapeDataString(property.Name));
174+
OpenApiPropertyAttribute? attribute = global::System.Reflection.CustomAttributeExtensions.GetCustomAttribute<OpenApiPropertyAttribute>(property);
175+
string name = attribute?.Name ?? property.Name;
176+
177+
queryString.Append(global::System.Uri.EscapeDataString(name));
131178
queryString.Append('=');
132179
queryString.Append(global::System.Uri.EscapeDataString(value));
133180
}
@@ -141,11 +188,20 @@ protected virtual void ResetStatusCode()
141188
return queryString.ToString();
142189
}
143190
}
191+
144192
""";
145193

146-
public static void AppendClass(StringBuilder builder, OpenApiContract contract)
194+
private static void AppendClass(
195+
StringBuilder builder,
196+
OpenApiContract contract,
197+
ClientGeneratorSerializer serializer
198+
)
147199
{
148-
builder.AppendLine(ClassHeader);
200+
builder.AppendLine(
201+
serializer == ClientGeneratorSerializer.SystemTextJson
202+
? SystemTextJsonClassHeader
203+
: NewtonsoftJsonClassHeader
204+
);
149205
int methodsCount = 0;
150206

151207
foreach (OpenApiPath path in contract.Paths)
@@ -192,17 +248,18 @@ public static void AppendClass(StringBuilder builder, OpenApiContract contract)
192248
$$$"""
193249
{
194250
string? responseBody = null;
251+
string[] pathParameters = new string[0];
195252
196253
try
197254
{
198255
responseBody = await ExecuteRequestAsync(
199256
global::System.Net.Http.HttpMethod.Get,
200-
{{{(
257+
ComputePath({{{(
201258
"\""
202259
+ path.Path
203260
+ "\""
204261
+ (path.RequestQueryType?.Length > 0 ? " + ComputeQueryString(query)" : null)
205-
)}}},
262+
)}}}, pathParameters),
206263
{{{(
207264
path.RequestBodyType?.Length > 0 ? "SerializeRequest(request)" : "null"
208265
)}}},
@@ -216,6 +273,7 @@ public static void AppendClass(StringBuilder builder, OpenApiContract contract)
216273
217274
return new %CLASS%Result(lastStatusCode);
218275
}
276+
219277
"""
220278
);
221279

src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Interface.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
using OpenApi.Client.SourceGenerators.Contracts;
77

8-
namespace OpenApi.Client.SourceGenerators.Genertion;
8+
namespace OpenApi.Client.SourceGenerators.Generation;
99

1010
internal sealed partial class ClientGenerator
1111
{
@@ -22,6 +22,7 @@ internal sealed partial class ClientGenerator
2222

2323
public const string InterfaceFooter = """
2424
}
25+
2526
""";
2627

2728
public static void AppendInterface(StringBuilder builder, OpenApiContract contract)

src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Result.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Copyright (C) Leszek Pomianowski and OpenAPI Client Contributors.
44
// All Rights Reserved.
55

6-
namespace OpenApi.Client.SourceGenerators.Genertion;
6+
namespace OpenApi.Client.SourceGenerators.Generation;
77

88
internal sealed partial class ClientGenerator
99
{
@@ -21,10 +21,21 @@ internal sealed partial class ClientGenerator
2121
/// <summary>Gets the error message.</summary>
2222
public string? Message { get; }
2323
}
24+
25+
/// <summary>Represents a result of the API call.</summary>
26+
[global::System.CodeDom.Compiler.GeneratedCode("OpenApiClient", "%VERSION%")]
27+
%ACCESS% interface I%CLASS%Result
28+
{
29+
/// <summary>Gets a value indicating whether the API call has errors.</summary>
30+
bool HasErrors { get; }
31+
32+
/// <summary>Gets a value indicating whether the API call succeeded.</summary>
33+
bool IsSucceeded{ get; }
34+
}
2435
2536
/// <summary>Represents a result of the API call.</summary>
2637
[global::System.CodeDom.Compiler.GeneratedCode("OpenApiClient", "%VERSION%")]
27-
%ACCESS% class %CLASS%Result
38+
%ACCESS% class %CLASS%Result : I%CLASS%Result
2839
{
2940
/// <summary>Initializes a new instance of the class.</summary>
3041
/// <param name="errors">The errors of the API call.</param>
@@ -47,14 +58,23 @@ internal sealed partial class ClientGenerator
4758
/// <summary>Gets the errors of the API call.</summary>
4859
public %CLASS%ResultError[] Errors { get; }
4960
50-
/// <summary>Gets a value indicating whether the API call has errors.</summary>
61+
/// <inheritdoc/>
5162
public bool HasErrors
5263
{
5364
get
5465
{
5566
return Errors.Length > 0;
5667
}
5768
}
69+
70+
/// <inheritdoc/>
71+
public bool IsSucceeded
72+
{
73+
get
74+
{
75+
return !HasErrors;
76+
}
77+
}
5878
}
5979
6080
/// <summary>Represents a result from the API.</summary>

0 commit comments

Comments
 (0)