diff options
Diffstat (limited to 'MediaBrowser.Common/Json')
6 files changed, 231 insertions, 0 deletions
diff --git a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs b/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs new file mode 100644 index 000000000..a259cb7bc --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs @@ -0,0 +1,75 @@ +using System; +using System.ComponentModel; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// <summary> + /// Convert comma delimited string to array of type. + /// </summary> + /// <typeparam name="T">Type to convert to.</typeparam> + public class JsonCommaDelimitedArrayConverter<T> : JsonConverter<T[]> + { + private readonly TypeConverter _typeConverter; + + /// <summary> + /// Initializes a new instance of the <see cref="JsonCommaDelimitedArrayConverter{T}"/> class. + /// </summary> + public JsonCommaDelimitedArrayConverter() + { + _typeConverter = TypeDescriptor.GetConverter(typeof(T)); + } + + /// <inheritdoc /> + public override T[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + var stringEntries = reader.GetString()?.Split(',', StringSplitOptions.RemoveEmptyEntries); + if (stringEntries == null || stringEntries.Length == 0) + { + return Array.Empty<T>(); + } + + var parsedValues = new object[stringEntries.Length]; + var convertedCount = 0; + for (var i = 0; i < stringEntries.Length; i++) + { + try + { + parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim()); + convertedCount++; + } + catch (FormatException) + { + // TODO log when upgraded to .Net6 + // https://github.com/dotnet/runtime/issues/42975 + // _logger.LogWarning(e, "Error converting value."); + } + } + + var typedValues = new T[convertedCount]; + var typedValueIndex = 0; + for (var i = 0; i < stringEntries.Length; i++) + { + if (parsedValues[i] != null) + { + typedValues.SetValue(parsedValues[i], typedValueIndex); + typedValueIndex++; + } + } + + return typedValues; + } + + return JsonSerializer.Deserialize<T[]>(ref reader, options); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, T[] value, JsonSerializerOptions options) + { + JsonSerializer.Serialize(writer, value, options); + } + } +} diff --git a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs b/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs new file mode 100644 index 000000000..24ed3ea19 --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs @@ -0,0 +1,28 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// <summary> + /// Json comma delimited array converter factory. + /// </summary> + /// <remarks> + /// This must be applied as an attribute, adding to the JsonConverter list causes stack overflow. + /// </remarks> + public class JsonCommaDelimitedArrayConverterFactory : JsonConverterFactory + { + /// <inheritdoc /> + public override bool CanConvert(Type typeToConvert) + { + return true; + } + + /// <inheritdoc /> + public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0]; + return (JsonConverter)Activator.CreateInstance(typeof(JsonCommaDelimitedArrayConverter<>).MakeGenericType(structType)); + } + } +} diff --git a/MediaBrowser.Common/Json/Converters/JsonDateTimeIso8601Converter.cs b/MediaBrowser.Common/Json/Converters/JsonDateTimeIso8601Converter.cs new file mode 100644 index 000000000..63b344a9d --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonDateTimeIso8601Converter.cs @@ -0,0 +1,24 @@ +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// <summary> + /// Returns an ISO8601 formatted datetime. + /// </summary> + /// <remarks> + /// Used for legacy compatibility. + /// </remarks> + public class JsonDateTimeIso8601Converter : JsonConverter<DateTime> + { + /// <inheritdoc /> + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => reader.GetDateTime(); + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString("O", CultureInfo.InvariantCulture)); + } +} diff --git a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs b/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs new file mode 100644 index 000000000..75fbcea1f --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs @@ -0,0 +1,75 @@ +using System; +using System.ComponentModel; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// <summary> + /// Convert Pipe delimited string to array of type. + /// </summary> + /// <typeparam name="T">Type to convert to.</typeparam> + public class JsonPipeDelimitedArrayConverter<T> : JsonConverter<T[]> + { + private readonly TypeConverter _typeConverter; + + /// <summary> + /// Initializes a new instance of the <see cref="JsonPipeDelimitedArrayConverter{T}"/> class. + /// </summary> + public JsonPipeDelimitedArrayConverter() + { + _typeConverter = TypeDescriptor.GetConverter(typeof(T)); + } + + /// <inheritdoc /> + public override T[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + var stringEntries = reader.GetString()?.Split('|', StringSplitOptions.RemoveEmptyEntries); + if (stringEntries == null || stringEntries.Length == 0) + { + return Array.Empty<T>(); + } + + var parsedValues = new object[stringEntries.Length]; + var convertedCount = 0; + for (var i = 0; i < stringEntries.Length; i++) + { + try + { + parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim()); + convertedCount++; + } + catch (FormatException) + { + // TODO log when upgraded to .Net6 + // https://github.com/dotnet/runtime/issues/42975 + // _logger.LogWarning(e, "Error converting value."); + } + } + + var typedValues = new T[convertedCount]; + var typedValueIndex = 0; + for (var i = 0; i < stringEntries.Length; i++) + { + if (parsedValues[i] != null) + { + typedValues.SetValue(parsedValues[i], typedValueIndex); + typedValueIndex++; + } + } + + return typedValues; + } + + return JsonSerializer.Deserialize<T[]>(ref reader, options); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, T[] value, JsonSerializerOptions options) + { + JsonSerializer.Serialize(writer, value, options); + } + } +} diff --git a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs b/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs new file mode 100644 index 000000000..5e77223ef --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs @@ -0,0 +1,28 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// <summary> + /// Json Pipe delimited array converter factory. + /// </summary> + /// <remarks> + /// This must be applied as an attribute, adding to the JsonConverter list causes stack overflow. + /// </remarks> + public class JsonPipeDelimitedArrayConverterFactory : JsonConverterFactory + { + /// <inheritdoc /> + public override bool CanConvert(Type typeToConvert) + { + return true; + } + + /// <inheritdoc /> + public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0]; + return (JsonConverter)Activator.CreateInstance(typeof(JsonPipeDelimitedArrayConverter<>).MakeGenericType(structType)); + } + } +} diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index 6605ae962..9a94664ac 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -42,6 +42,7 @@ namespace MediaBrowser.Common.Json options.Converters.Add(new JsonGuidConverter()); options.Converters.Add(new JsonStringEnumConverter()); options.Converters.Add(new JsonNullableStructConverterFactory()); + options.Converters.Add(new JsonDateTimeIso8601Converter()); return options; } |
