-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJSONstat.cs
More file actions
105 lines (90 loc) · 5.36 KB
/
Copy pathJSONstat.cs
File metadata and controls
105 lines (90 loc) · 5.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System;
using System.IO;
using System.Net.Http;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using JSONstat.IO;
using JSONstat.Models;
namespace JSONstat;
/// <summary>
/// Entry point for reading and writing JSON-stat v2.0, mirroring the JavaScript
/// Toolkit's <c>JSONstat</c> function. Use <see cref="Parse(string)"/> to read a
/// response and <see cref="Serialize(Response)"/> to write one back.
/// </summary>
public static class JSONstat
{
/// <summary>The JSON-stat format version this library targets.</summary>
public const string FormatVersion = "2.0";
/// <summary>
/// A shared <see cref="HttpClient"/> used by <see cref="LoadAsync(Uri, HttpClient?, CancellationToken)"/>
/// when no client is supplied. Reusing a single client avoids socket exhaustion
/// (see https://learn.microsoft.com/dotnet/api/system.net.http.httpclient).
/// </summary>
private static readonly HttpClient s_sharedClient = new HttpClient();
/// <summary>Parses a JSON-stat response from a UTF-8 string.</summary>
public static Response Parse(string json) =>
JsonSerializer.Deserialize<Response>(json, JsonOptions.Default)
?? throw new JsonException("Invalid JSON-stat response (null result).");
/// <summary>Parses a JSON-stat response from a stream (synchronous).</summary>
public static Response Parse(Stream utf8Json) =>
ParseAsync(utf8Json).GetAwaiter().GetResult();
/// <summary>Parses a JSON-stat response from a stream asynchronously.</summary>
public static async Task<Response> ParseAsync(Stream utf8Json, CancellationToken cancellationToken = default)
{
var response = await JsonSerializer.DeserializeAsync<Response>(utf8Json, JsonOptions.Default, cancellationToken).ConfigureAwait(false);
return response ?? throw new JsonException("Invalid JSON-stat response (null result).");
}
/// <summary>Parses a JSON-stat response from an already-read <see cref="JsonElement"/>.</summary>
public static Response Parse(JsonElement element) =>
element.Deserialize<Response>(JsonOptions.Default)
?? throw new JsonException("Invalid JSON-stat response (null result).");
/// <summary>Serializes a response to a JSON string.</summary>
public static string Serialize(Response response) =>
JsonSerializer.Serialize(response, JsonOptions.Default);
/// <summary>Serializes a standalone dataset to a JSON string.</summary>
public static string Serialize(Dataset dataset) =>
JsonSerializer.Serialize(dataset, JsonOptions.Default);
/// <summary>Serializes a response to a stream (synchronous).</summary>
public static void Serialize(Stream utf8Json, Response response) =>
JsonSerializer.Serialize(utf8Json, response, JsonOptions.Default);
/// <summary>Serializes a response to a stream asynchronously.</summary>
public static Task SerializeAsync(Stream utf8Json, Response response, CancellationToken cancellationToken = default) =>
JsonSerializer.SerializeAsync(utf8Json, response, JsonOptions.Default, cancellationToken);
/// <summary>
/// Fetches a JSON-stat response from <paramref name="url"/> (HTTP GET) and parses it,
/// mirroring the JavaScript Toolkit's <c>JSONstat(url)</c>. Uses the shared internal
/// <see cref="HttpClient"/>. Synchronous wrapper over <see cref="LoadAsync(Uri, HttpClient?, CancellationToken)"/>.
/// </summary>
public static Response Load(Uri url) => Load(url, client: null);
/// <summary>
/// Fetches a JSON-stat response from <paramref name="url"/> (HTTP GET) using the supplied
/// <paramref name="client"/> and parses it. Synchronous wrapper over
/// <see cref="LoadAsync(Uri, HttpClient?, CancellationToken)"/>.
/// </summary>
public static Response Load(Uri url, HttpClient? client) =>
LoadAsync(url, client).GetAwaiter().GetResult();
/// <summary>
/// Fetches and parses a JSON-stat response from <paramref name="url"/> asynchronously,
/// using the shared internal <see cref="HttpClient"/>. Equivalent to the JavaScript
/// Toolkit's <c>JSONstat(url)</c>.
/// </summary>
public static Task<Response> LoadAsync(Uri url, CancellationToken cancellationToken = default) =>
LoadAsync(url, client: null, cancellationToken);
/// <summary>
/// Fetches and parses a JSON-stat response from <paramref name="url"/> asynchronously.
/// When <paramref name="client"/> is <c>null</c>, a shared internal <see cref="HttpClient"/>
/// is used; pass your own to customize base address, headers, timeout, or handler (e.g. for tests).
/// </summary>
/// <exception cref="ArgumentNullException"><paramref name="url"/> is <c>null</c>.</exception>
/// <exception cref="HttpRequestException">The request failed or returned a non-success status.</exception>
public static async Task<Response> LoadAsync(Uri url, HttpClient? client, CancellationToken cancellationToken = default)
{
if (url is null) throw new ArgumentNullException(nameof(url));
var http = client ?? s_sharedClient;
using var response = await http.GetAsync(url, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return await ParseAsync(stream, cancellationToken).ConfigureAwait(false);
}
}