From 384a62dc0883549b328dc1f70d19358ae0aa593e Mon Sep 17 00:00:00 2001 From: crobibero Date: Fri, 21 Aug 2020 10:23:47 -0600 Subject: [PATCH 1/2] Add nullable int32, int64 json converters --- .../Converters/JsonNullableInt32Converter.cs | 55 +++++++++++++++ .../Converters/JsonNullableInt64Converter.cs | 70 +++++++++++++++++++ MediaBrowser.Common/Json/JsonDefaults.cs | 2 + 3 files changed, 127 insertions(+) create mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs create mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs new file mode 100644 index 0000000000..c4579d989d --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs @@ -0,0 +1,55 @@ +using System; +using System.Buffers; +using System.Buffers.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// + /// Converts a GUID object or value to/from JSON. + /// + public class JsonNullableInt32Converter : JsonConverter + { + /// + public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + ReadOnlySpan span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; + if (Utf8Parser.TryParse(span, out int number, out int bytesConsumed) && span.Length == bytesConsumed) + { + return number; + } + + var stringValue = reader.GetString().AsSpan(); + + // value is null or empty, just return null. + if (stringValue.IsEmpty) + { + return null; + } + + if (int.TryParse(stringValue, out number)) + { + return number; + } + } + + return reader.GetInt32(); + } + + /// + public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options) + { + if (value is null) + { + writer.WriteNullValue(); + } + else + { + writer.WriteNumberValue(value.Value); + } + } + } +} diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs new file mode 100644 index 0000000000..53e5f6e9df --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs @@ -0,0 +1,70 @@ +using System; +using System.Buffers; +using System.Buffers.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// + /// Parse JSON string as nullable long. + /// Javascript does not support 64-bit integers. + /// + public class JsonNullableInt64Converter : JsonConverter + { + /// + /// Read JSON string as int64. + /// + /// . + /// Type. + /// Options. + /// Parsed value. + public override long? Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + // try to parse number directly from bytes + var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; + if (Utf8Parser.TryParse(span, out long number, out var bytesConsumed) && span.Length == bytesConsumed) + { + return number; + } + + var stringValue = reader.GetString().AsSpan(); + + // value is null or empty, just return null. + if (stringValue.IsEmpty) + { + return null; + } + + // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters + if (long.TryParse(stringValue, out number)) + { + return number; + } + } + + // fallback to default handling + return reader.GetInt64(); + } + + /// + /// Write long to JSON long. + /// + /// . + /// Value to write. + /// Options. + public override void Write(Utf8JsonWriter writer, long? value, JsonSerializerOptions options) + { + if (value is null) + { + writer.WriteNullValue(); + } + else + { + writer.WriteNumberValue(value.Value); + } + } + } +} diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index 36ab6d900a..0a661934e5 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -29,9 +29,11 @@ namespace MediaBrowser.Common.Json options.Converters.Add(new JsonGuidConverter()); options.Converters.Add(new JsonInt32Converter()); + options.Converters.Add(new JsonNullableInt32Converter()); options.Converters.Add(new JsonStringEnumConverter()); options.Converters.Add(new JsonNonStringKeyDictionaryConverterFactory()); options.Converters.Add(new JsonInt64Converter()); + options.Converters.Add(new JsonNullableInt64Converter()); options.Converters.Add(new JsonDoubleConverter()); return options; From d9515547799d3832dff2d38d12bd4dda539a4e23 Mon Sep 17 00:00:00 2001 From: crobibero Date: Fri, 21 Aug 2020 14:37:51 -0600 Subject: [PATCH 2/2] fix copy-pasta --- MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs | 2 +- .../Json/Converters/JsonNullableInt32Converter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs index 70c375b8cd..7ed9d6766d 100644 --- a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs +++ b/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs @@ -7,7 +7,7 @@ using System.Text.Json.Serialization; namespace MediaBrowser.Common.Json.Converters { /// - /// Converts a GUID object or value to/from JSON. + /// Converts a int32 object or value to/from JSON. /// public class JsonInt32Converter : JsonConverter { diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs index c4579d989d..c1660fe761 100644 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs +++ b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs @@ -7,7 +7,7 @@ using System.Text.Json.Serialization; namespace MediaBrowser.Common.Json.Converters { /// - /// Converts a GUID object or value to/from JSON. + /// Converts a nullable int32 object or value to/from JSON. /// public class JsonNullableInt32Converter : JsonConverter {