Skip to content

Commit 513a3fe

Browse files
committed
feat: Replace JSON.NET with System.Text.Json
1 parent 0c69aca commit 513a3fe

File tree

316 files changed

+1976
-2297
lines changed

Some content is hidden

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

316 files changed

+1976
-2297
lines changed

src/Docker.DotNet/Docker.DotNet.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
<PackageId>Docker.DotNet.Enhanced</PackageId>
44
<Description>Docker.DotNet is a library that allows you to interact with the Docker Remote API programmatically with fully asynchronous, non-blocking and object-oriented code in your .NET applications.</Description>
55
<AssemblyName>Docker.DotNet</AssemblyName>
6+
<LangVersion>latest</LangVersion>
67
</PropertyGroup>
78
<ItemGroup>
8-
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
99
<PackageReference Include="System.Buffers" Version="4.5.1" />
10+
<PackageReference Include="System.IO.Pipelines" Version="8.0.0" />
11+
<PackageReference Include="System.Net.Http.Json" Version="8.0.1" />
12+
<PackageReference Include="System.Text.Json" Version="8.0.5" />
1013
</ItemGroup>
1114
</Project>

src/Docker.DotNet/DockerClient.cs

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ internal DockerClient(DockerClientConfiguration configuration, Version requested
3333
Configuration = configuration;
3434
DefaultTimeout = configuration.DefaultTimeout;
3535

36-
JsonSerializer = new JsonSerializer();
3736
Images = new ImageOperations(this);
3837
Containers = new ContainerOperations(this);
3938
System = new SystemOperations(this);
@@ -149,57 +148,100 @@ await sock.ConnectAsync(new Microsoft.Net.Http.Client.UnixDomainSocketEndPoint(p
149148

150149
public IExecOperations Exec { get; }
151150

152-
internal JsonSerializer JsonSerializer { get; }
151+
internal JsonSerializer JsonSerializer => JsonSerializer.Instance;
153152

154153
public void Dispose()
155154
{
156155
Configuration.Dispose();
157156
_client.Dispose();
158157
}
159158

160-
internal Task<DockerApiResponse> MakeRequestAsync(
159+
internal Task MakeRequestAsync(
161160
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
162161
HttpMethod method,
163162
string path,
164163
CancellationToken token)
165164
{
166-
return MakeRequestAsync(errorHandlers, method, path, null, null, token);
165+
return MakeRequestAsync<NoContent>(errorHandlers, method, path, null, null, token);
167166
}
168167

169-
internal Task<DockerApiResponse> MakeRequestAsync(
168+
internal Task<T> MakeRequestAsync<T>(
169+
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
170+
HttpMethod method,
171+
string path,
172+
CancellationToken token)
173+
{
174+
return MakeRequestAsync<T>(errorHandlers, method, path, null, null, token);
175+
}
176+
177+
internal Task MakeRequestAsync(
178+
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
179+
HttpMethod method,
180+
string path,
181+
IQueryString queryString,
182+
CancellationToken token)
183+
{
184+
return MakeRequestAsync<NoContent>(errorHandlers, method, path, queryString, null, token);
185+
}
186+
187+
internal Task<T> MakeRequestAsync<T>(
188+
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
189+
HttpMethod method,
190+
string path,
191+
IQueryString queryString,
192+
CancellationToken token)
193+
{
194+
return MakeRequestAsync<T>(errorHandlers, method, path, queryString, null, token);
195+
}
196+
197+
internal Task MakeRequestAsync(
198+
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
199+
HttpMethod method,
200+
string path,
201+
IQueryString queryString,
202+
IRequestContent body,
203+
CancellationToken token)
204+
{
205+
return MakeRequestAsync<NoContent>(errorHandlers, method, path, queryString, body, null, token);
206+
}
207+
208+
internal Task<T> MakeRequestAsync<T>(
170209
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
171210
HttpMethod method,
172211
string path,
173212
IQueryString queryString,
213+
IRequestContent body,
174214
CancellationToken token)
175215
{
176-
return MakeRequestAsync(errorHandlers, method, path, queryString, null, token);
216+
return MakeRequestAsync<T>(errorHandlers, method, path, queryString, body, null, token);
177217
}
178218

179-
internal Task<DockerApiResponse> MakeRequestAsync(
219+
internal Task<T> MakeRequestAsync<T>(
180220
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
181221
HttpMethod method,
182222
string path,
183223
IQueryString queryString,
184224
IRequestContent body,
225+
IDictionary<string, string> headers,
185226
CancellationToken token)
186227
{
187-
return MakeRequestAsync(errorHandlers, method, path, queryString, body, null, token);
228+
return MakeRequestAsync<T>(errorHandlers, method, path, queryString, body, headers, DefaultTimeout, token);
188229
}
189230

190-
internal Task<DockerApiResponse> MakeRequestAsync(
231+
internal Task MakeRequestAsync(
191232
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
192233
HttpMethod method,
193234
string path,
194235
IQueryString queryString,
195236
IRequestContent body,
196237
IDictionary<string, string> headers,
238+
TimeSpan timeout,
197239
CancellationToken token)
198240
{
199-
return MakeRequestAsync(errorHandlers, method, path, queryString, body, headers, DefaultTimeout, token);
241+
return MakeRequestAsync<NoContent>(errorHandlers, method, path, queryString, body, headers, timeout, token);
200242
}
201243

202-
internal async Task<DockerApiResponse> MakeRequestAsync(
244+
internal async Task<T> MakeRequestAsync<T>(
203245
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
204246
HttpMethod method,
205247
string path,
@@ -217,10 +259,13 @@ internal async Task<DockerApiResponse> MakeRequestAsync(
217259
await HandleIfErrorResponseAsync(response.StatusCode, response, errorHandlers)
218260
.ConfigureAwait(false);
219261

220-
var responseBody = await response.Content.ReadAsStringAsync()
221-
.ConfigureAwait(false);
262+
if (typeof(T) == typeof(NoContent))
263+
{
264+
return default;
265+
}
222266

223-
return new DockerApiResponse(response.StatusCode, responseBody);
267+
return await JsonSerializer.DeserializeAsync<T>(response.Content, token)
268+
.ConfigureAwait(false);
224269
}
225270
}
226271

@@ -294,7 +339,7 @@ internal async Task<HttpResponseMessage> MakeRequestForRawResponseAsync(
294339
IDictionary<string, string> headers,
295340
CancellationToken token)
296341
{
297-
var response = await PrivateMakeRequestAsync(SInfiniteTimeout, HttpCompletionOption.ResponseHeadersRead, method, path, queryString, headers, body, token).ConfigureAwait(false);
342+
var response = await PrivateMakeRequestAsync(SInfiniteTimeout, HttpCompletionOption.ResponseHeadersRead, method, path, queryString, headers, body, token).ConfigureAwait(false);
298343
await HandleIfErrorResponseAsync(response.StatusCode, response)
299344
.ConfigureAwait(false);
300345
return response;
@@ -469,6 +514,8 @@ private async Task HandleIfErrorResponseAsync(HttpStatusCode statusCode, HttpRes
469514
throw new DockerApiException(statusCode, responseBody);
470515
}
471516
}
517+
518+
private struct NoContent {}
472519
}
473520

474521
internal delegate void ApiResponseErrorHandlingDelegate(HttpStatusCode statusCode, string responseBody);

src/Docker.DotNet/Endpoints/ConfigsOperations.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ internal ConfigOperations(DockerClient client)
1818

1919
async Task<IList<SwarmConfig>> IConfigOperations.ListConfigsAsync(CancellationToken cancellationToken)
2020
{
21-
var response = await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken).ConfigureAwait(false);
22-
return _client.JsonSerializer.DeserializeObject<IList<SwarmConfig>>(response.Body);
21+
return await _client.MakeRequestAsync<IList<SwarmConfig>>(_client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken).ConfigureAwait(false);
2322
}
2423

2524
async Task<SwarmCreateConfigResponse> IConfigOperations.CreateConfigAsync(SwarmCreateConfigParameters body, CancellationToken cancellationToken)
@@ -30,8 +29,7 @@ async Task<SwarmCreateConfigResponse> IConfigOperations.CreateConfigAsync(SwarmC
3029
}
3130

3231
var data = new JsonRequestContent<SwarmConfigSpec>(body.Config, _client.JsonSerializer);
33-
var response = await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Post, "configs/create", null, data, cancellationToken).ConfigureAwait(false);
34-
return _client.JsonSerializer.DeserializeObject<SwarmCreateConfigResponse>(response.Body);
32+
return await _client.MakeRequestAsync<SwarmCreateConfigResponse>(_client.NoErrorHandlers, HttpMethod.Post, "configs/create", null, data, cancellationToken).ConfigureAwait(false);
3533
}
3634

3735
async Task<SwarmConfig> IConfigOperations.InspectConfigAsync(string id, CancellationToken cancellationToken)
@@ -41,8 +39,7 @@ async Task<SwarmConfig> IConfigOperations.InspectConfigAsync(string id, Cancella
4139
throw new ArgumentNullException(nameof(id));
4240
}
4341

44-
var response = await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Get, $"configs/{id}", cancellationToken).ConfigureAwait(false);
45-
return _client.JsonSerializer.DeserializeObject<SwarmConfig>(response.Body);
42+
return await _client.MakeRequestAsync<SwarmConfig>(_client.NoErrorHandlers, HttpMethod.Get, $"configs/{id}", cancellationToken).ConfigureAwait(false);
4643
}
4744

4845
Task IConfigOperations.RemoveConfigAsync(string id, CancellationToken cancellationToken)
@@ -55,4 +52,4 @@ Task IConfigOperations.RemoveConfigAsync(string id, CancellationToken cancellati
5552
return _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Delete, $"configs/{id}", cancellationToken);
5653
}
5754
}
58-
}
55+
}

src/Docker.DotNet/Endpoints/ContainerOperations.cs

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.Linq;
66
using System.Net;
77
using System.Net.Http;
8-
using System.Text;
98
using System.Threading;
109
using System.Threading.Tasks;
1110

@@ -43,8 +42,7 @@ internal ContainerOperations(DockerClient client)
4342
}
4443

4544
IQueryString queryParameters = new QueryString<ContainersListParameters>(parameters);
46-
var response = await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Get, "containers/json", queryParameters, cancellationToken).ConfigureAwait(false);
47-
return _client.JsonSerializer.DeserializeObject<ContainerListResponse[]>(response.Body);
45+
return await _client.MakeRequestAsync<ContainerListResponse[]>(_client.NoErrorHandlers, HttpMethod.Get, "containers/json", queryParameters, cancellationToken).ConfigureAwait(false);
4846
}
4947

5048
public async Task<CreateContainerResponse> CreateContainerAsync(CreateContainerParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
@@ -62,8 +60,7 @@ internal ContainerOperations(DockerClient client)
6260
}
6361

6462
var data = new JsonRequestContent<CreateContainerParameters>(parameters, _client.JsonSerializer);
65-
var response = await _client.MakeRequestAsync(new[] { NoSuchImageHandler }, HttpMethod.Post, "containers/create", qs, data, cancellationToken).ConfigureAwait(false);
66-
return _client.JsonSerializer.DeserializeObject<CreateContainerResponse>(response.Body);
63+
return await _client.MakeRequestAsync<CreateContainerResponse>(new[] { NoSuchImageHandler }, HttpMethod.Post, "containers/create", qs, data, cancellationToken).ConfigureAwait(false);
6764
}
6865

6966
public async Task<ContainerInspectResponse> InspectContainerAsync(string id, CancellationToken cancellationToken = default(CancellationToken))
@@ -73,8 +70,7 @@ internal ContainerOperations(DockerClient client)
7370
throw new ArgumentNullException(nameof(id));
7471
}
7572

76-
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/json", cancellationToken).ConfigureAwait(false);
77-
return _client.JsonSerializer.DeserializeObject<ContainerInspectResponse>(response.Body);
73+
return await _client.MakeRequestAsync<ContainerInspectResponse>(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/json", cancellationToken).ConfigureAwait(false);
7874
}
7975

8076
public async Task<ContainerProcessesResponse> ListProcessesAsync(string id, ContainerListProcessesParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
@@ -90,8 +86,7 @@ internal ContainerOperations(DockerClient client)
9086
}
9187

9288
IQueryString queryParameters = new QueryString<ContainerListProcessesParameters>(parameters);
93-
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/top", queryParameters, cancellationToken).ConfigureAwait(false);
94-
return _client.JsonSerializer.DeserializeObject<ContainerProcessesResponse>(response.Body);
89+
return await _client.MakeRequestAsync<ContainerProcessesResponse>(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/top", queryParameters, cancellationToken).ConfigureAwait(false);
9590
}
9691

9792
public Task<Stream> GetContainerLogsAsync(string id, ContainerLogsParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
@@ -145,8 +140,7 @@ public Task GetContainerLogsAsync(string id, ContainerLogsParameters parameters,
145140
throw new ArgumentNullException(nameof(id));
146141
}
147142

148-
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/changes", cancellationToken).ConfigureAwait(false);
149-
return _client.JsonSerializer.DeserializeObject<ContainerFileSystemChangeResponse[]>(response.Body);
143+
return await _client.MakeRequestAsync<ContainerFileSystemChangeResponse[]>(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/changes", cancellationToken).ConfigureAwait(false);
150144
}
151145

152146
public Task<Stream> ExportContainerAsync(string id, CancellationToken cancellationToken)
@@ -208,8 +202,9 @@ public Task<Stream> GetContainerStatsAsync(string id, ContainerStatsParameters p
208202
}
209203

210204
var queryParams = parameters == null ? null : new QueryString<ContainerStartParameters>(parameters);
211-
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/start", queryParams, cancellationToken).ConfigureAwait(false);
212-
return response.StatusCode != HttpStatusCode.NotModified;
205+
bool? result = null;
206+
await _client.MakeRequestAsync(new[] { NoSuchContainerHandler, (statusCode, _) => result = statusCode != HttpStatusCode.NotModified }, HttpMethod.Post, $"containers/{id}/start", queryParams, cancellationToken).ConfigureAwait(false);
207+
return result ?? throw new InvalidOperationException();
213208
}
214209

215210
public async Task<bool> StopContainerAsync(string id, ContainerStopParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
@@ -227,8 +222,9 @@ public Task<Stream> GetContainerStatsAsync(string id, ContainerStatsParameters p
227222
IQueryString queryParameters = new QueryString<ContainerStopParameters>(parameters);
228223
// since specified wait timespan can be greater than HttpClient's default, we set the
229224
// client timeout to infinite and provide a cancellation token.
230-
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/stop", queryParameters, null, null, TimeSpan.FromMilliseconds(Timeout.Infinite), cancellationToken).ConfigureAwait(false);
231-
return response.StatusCode != HttpStatusCode.NotModified;
225+
bool? result = null;
226+
await _client.MakeRequestAsync(new[] { NoSuchContainerHandler, (statusCode, _) => result = statusCode != HttpStatusCode.NotModified }, HttpMethod.Post, $"containers/{id}/stop", queryParameters, null, null, TimeSpan.FromMilliseconds(Timeout.Infinite), cancellationToken).ConfigureAwait(false);
227+
return result ?? throw new InvalidOperationException();
232228
}
233229

234230
public Task RestartContainerAsync(string id, ContainerRestartParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
@@ -327,8 +323,7 @@ public Task RenameContainerAsync(string id, ContainerRenameParameters parameters
327323
throw new ArgumentNullException(nameof(id));
328324
}
329325

330-
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/wait", null, null, null, TimeSpan.FromMilliseconds(Timeout.Infinite), cancellationToken).ConfigureAwait(false);
331-
return _client.JsonSerializer.DeserializeObject<ContainerWaitResponse>(response.Body);
326+
return await _client.MakeRequestAsync<ContainerWaitResponse>(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/wait", null, null, null, TimeSpan.FromMilliseconds(Timeout.Infinite), cancellationToken).ConfigureAwait(false);
332327
}
333328

334329
public Task RemoveContainerAsync(string id, ContainerRemoveParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
@@ -367,9 +362,7 @@ public Task RenameContainerAsync(string id, ContainerRenameParameters parameters
367362

368363
var bytes = Convert.FromBase64String(statHeader);
369364

370-
var stat = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
371-
372-
var pathStat = _client.JsonSerializer.DeserializeObject<ContainerPathStatResponse>(stat);
365+
var pathStat = _client.JsonSerializer.Deserialize<ContainerPathStatResponse>(bytes);
373366

374367
return new GetArchiveFromContainerResponse
375368
{
@@ -399,8 +392,7 @@ public Task RenameContainerAsync(string id, ContainerRenameParameters parameters
399392
public async Task<ContainersPruneResponse> PruneContainersAsync(ContainersPruneParameters parameters, CancellationToken cancellationToken)
400393
{
401394
var queryParameters = parameters == null ? null : new QueryString<ContainersPruneParameters>(parameters);
402-
var response = await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Post, "containers/prune", queryParameters, cancellationToken).ConfigureAwait(false);
403-
return _client.JsonSerializer.DeserializeObject<ContainersPruneResponse>(response.Body);
395+
return await _client.MakeRequestAsync<ContainersPruneResponse>(_client.NoErrorHandlers, HttpMethod.Post, "containers/prune", queryParameters, cancellationToken).ConfigureAwait(false);
404396
}
405397

406398
public async Task<ContainerUpdateResponse> UpdateContainerAsync(string id, ContainerUpdateParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
@@ -416,8 +408,7 @@ public async Task<ContainersPruneResponse> PruneContainersAsync(ContainersPruneP
416408
}
417409

418410
var data = new JsonRequestContent<ContainerUpdateParameters>(parameters, _client.JsonSerializer);
419-
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/update", null, data, cancellationToken);
420-
return _client.JsonSerializer.DeserializeObject<ContainerUpdateResponse>(response.Body);
411+
return await _client.MakeRequestAsync<ContainerUpdateResponse>(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/update", null, data, cancellationToken);
421412
}
422413
}
423414
}

0 commit comments

Comments
 (0)