summaryrefslogtreecommitdiffstats
path: root/src/Cepis/LenientStringConverter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Cepis/LenientStringConverter.cs')
-rw-r--r--src/Cepis/LenientStringConverter.cs57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/Cepis/LenientStringConverter.cs b/src/Cepis/LenientStringConverter.cs
new file mode 100644
index 0000000..f76c917
--- /dev/null
+++ b/src/Cepis/LenientStringConverter.cs
@@ -0,0 +1,57 @@
+using System.Buffers;
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Cepis;
+
+/// <summary>
+/// Reads any scalar as a string, and a JSON <c>null</c> as the empty string.
+/// </summary>
+/// <remarks>
+/// The API documents every text field as a string and an absent one as
+/// <c>""</c>, never null. This converter makes a client that meets a
+/// <c>null</c>, or a code sent as a number, degrade to the documented shape
+/// instead of throwing: none of those is worth failing a whole lookup over.
+/// </remarks>
+internal sealed class LenientStringConverter : JsonConverter<string>
+{
+ public override bool HandleNull => true;
+
+ public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ switch (reader.TokenType)
+ {
+ case JsonTokenType.String:
+ return reader.GetString() ?? "";
+ case JsonTokenType.Null:
+ return "";
+ case JsonTokenType.True:
+ return "true";
+ case JsonTokenType.False:
+ return "false";
+ case JsonTokenType.Number:
+ var raw = reader.HasValueSequence
+ ? reader.ValueSequence.ToArray()
+ : reader.ValueSpan.ToArray();
+ return Encoding.UTF8.GetString(raw);
+ default:
+ throw new JsonException($"expected a string, got {reader.TokenType}");
+ }
+ }
+
+ public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
+ {
+ ArgumentNullException.ThrowIfNull(writer);
+ writer.WriteStringValue(value);
+ }
+
+ public override string ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
+ reader.GetString() ?? "";
+
+ public override void WriteAsPropertyName(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
+ {
+ ArgumentNullException.ThrowIfNull(writer);
+ writer.WritePropertyName(value);
+ }
+}