瀏覽代碼

Clean up json Converters

crobibero 4 年之前
父節點
當前提交
8b96881aa1

+ 1 - 0
Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs

@@ -169,6 +169,7 @@ namespace Jellyfin.Server.Extensions
                     options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling;
                     options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling;
                     options.JsonSerializerOptions.WriteIndented = jsonOptions.WriteIndented;
                     options.JsonSerializerOptions.WriteIndented = jsonOptions.WriteIndented;
                     options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition;
                     options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition;
+                    options.JsonSerializerOptions.NumberHandling = jsonOptions.NumberHandling;
 
 
                     options.JsonSerializerOptions.Converters.Clear();
                     options.JsonSerializerOptions.Converters.Clear();
                     foreach (var converter in jsonOptions.Converters)
                     foreach (var converter in jsonOptions.Converters)

+ 0 - 56
MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs

@@ -1,56 +0,0 @@
-using System;
-using System.Buffers;
-using System.Buffers.Text;
-using System.Globalization;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace MediaBrowser.Common.Json.Converters
-{
-    /// <summary>
-    /// Double to String JSON converter.
-    /// Web client send quoted doubles.
-    /// </summary>
-    public class JsonDoubleConverter : JsonConverter<double>
-    {
-        /// <summary>
-        /// Read JSON string as double.
-        /// </summary>
-        /// <param name="reader"><see cref="Utf8JsonReader"/>.</param>
-        /// <param name="typeToConvert">Type.</param>
-        /// <param name="options">Options.</param>
-        /// <returns>Parsed value.</returns>
-        public override double Read(ref Utf8JsonReader reader, Type typeToConvert, 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 double number, out var bytesConsumed) && span.Length == bytesConsumed)
-                {
-                    return number;
-                }
-
-                // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters
-                if (double.TryParse(reader.GetString(), out number))
-                {
-                    return number;
-                }
-            }
-
-            // fallback to default handling
-            return reader.GetDouble();
-        }
-
-        /// <summary>
-        /// Write double to JSON string.
-        /// </summary>
-        /// <param name="writer"><see cref="Utf8JsonWriter"/>.</param>
-        /// <param name="value">Value to write.</param>
-        /// <param name="options">Options.</param>
-        public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options)
-        {
-            writer.WriteNumberValue(value);
-        }
-    }
-}

+ 0 - 40
MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs

@@ -1,40 +0,0 @@
-using System;
-using System.Buffers;
-using System.Buffers.Text;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace MediaBrowser.Common.Json.Converters
-{
-    /// <summary>
-    /// Converts a int32 object or value to/from JSON.
-    /// </summary>
-    public class JsonInt32Converter : JsonConverter<int>
-    {
-        /// <inheritdoc />
-        public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
-        {
-            if (reader.TokenType == JsonTokenType.String)
-            {
-                ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
-                if (Utf8Parser.TryParse(span, out int number, out int bytesConsumed) && span.Length == bytesConsumed)
-                {
-                    return number;
-                }
-
-                if (int.TryParse(reader.GetString(), out number))
-                {
-                    return number;
-                }
-            }
-
-            return reader.GetInt32();
-        }
-
-        /// <inheritdoc />
-        public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
-        {
-            writer.WriteNumberValue(value);
-        }
-    }
-}

+ 0 - 56
MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs

@@ -1,56 +0,0 @@
-using System;
-using System.Buffers;
-using System.Buffers.Text;
-using System.Globalization;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace MediaBrowser.Common.Json.Converters
-{
-    /// <summary>
-    /// Parse JSON string as long.
-    /// Javascript does not support 64-bit integers.
-    /// </summary>
-    public class JsonInt64Converter : JsonConverter<long>
-    {
-        /// <summary>
-        /// Read JSON string as int64.
-        /// </summary>
-        /// <param name="reader"><see cref="Utf8JsonReader"/>.</param>
-        /// <param name="type">Type.</param>
-        /// <param name="options">Options.</param>
-        /// <returns>Parsed value.</returns>
-        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;
-                }
-
-                // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters
-                if (long.TryParse(reader.GetString(), out number))
-                {
-                    return number;
-                }
-            }
-
-            // fallback to default handling
-            return reader.GetInt64();
-        }
-
-        /// <summary>
-        /// Write long to JSON long.
-        /// </summary>
-        /// <param name="writer"><see cref="Utf8JsonWriter"/>.</param>
-        /// <param name="value">Value to write.</param>
-        /// <param name="options">Options.</param>
-        public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options)
-        {
-            writer.WriteNumberValue(value);
-        }
-    }
-}

+ 0 - 82
MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs

@@ -1,82 +0,0 @@
-#nullable enable
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Reflection;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace MediaBrowser.Common.Json.Converters
-{
-    /// <summary>
-    /// Converter for Dictionaries without string key.
-    /// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys.
-    /// </summary>
-    /// <typeparam name="TKey">Type of key.</typeparam>
-    /// <typeparam name="TValue">Type of value.</typeparam>
-    internal sealed class JsonNonStringKeyDictionaryConverter<TKey, TValue> : JsonConverter<IDictionary<TKey, TValue>>
-    {
-        /// <summary>
-        /// Read JSON.
-        /// </summary>
-        /// <param name="reader">The Utf8JsonReader.</param>
-        /// <param name="typeToConvert">The type to convert.</param>
-        /// <param name="options">The json serializer options.</param>
-        /// <returns>Typed dictionary.</returns>
-        /// <exception cref="NotSupportedException">Dictionary key type not supported.</exception>
-        public override IDictionary<TKey, TValue> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
-        {
-            var convertedType = typeof(Dictionary<,>).MakeGenericType(typeof(string), typeToConvert.GenericTypeArguments[1]);
-            var value = JsonSerializer.Deserialize(ref reader, convertedType, options);
-            var instance = (Dictionary<TKey, TValue>)Activator.CreateInstance(
-                typeToConvert,
-                BindingFlags.Instance | BindingFlags.Public,
-                null,
-                null,
-                CultureInfo.CurrentCulture);
-            var enumerator = (IEnumerator)convertedType.GetMethod("GetEnumerator")!.Invoke(value, null);
-            var parse = typeof(TKey).GetMethod(
-                "Parse",
-                0,
-                BindingFlags.Public | BindingFlags.Static,
-                null,
-                CallingConventions.Any,
-                new[] { typeof(string) },
-                null);
-            if (parse == null)
-            {
-                throw new NotSupportedException($"{typeof(TKey)} as TKey in IDictionary<TKey, TValue> is not supported.");
-            }
-
-            while (enumerator.MoveNext())
-            {
-                var element = (KeyValuePair<string?, TValue>)enumerator.Current;
-                instance.Add((TKey)parse.Invoke(null, new[] { (object?)element.Key }), element.Value);
-            }
-
-            return instance;
-        }
-
-        /// <summary>
-        /// Write dictionary as Json.
-        /// </summary>
-        /// <param name="writer">The Utf8JsonWriter.</param>
-        /// <param name="value">The dictionary value.</param>
-        /// <param name="options">The Json serializer options.</param>
-        public override void Write(Utf8JsonWriter writer, IDictionary<TKey, TValue> value, JsonSerializerOptions options)
-        {
-            var convertedDictionary = new Dictionary<string?, TValue>(value.Count);
-            foreach (var (k, v) in value)
-            {
-                if (k != null)
-                {
-                    convertedDictionary[k.ToString()] = v;
-                }
-            }
-
-            JsonSerializer.Serialize(writer, convertedDictionary, options);
-        }
-    }
-}

+ 0 - 59
MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs

@@ -1,59 +0,0 @@
-#nullable enable
-
-using System;
-using System.Collections;
-using System.Globalization;
-using System.Reflection;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace MediaBrowser.Common.Json.Converters
-{
-    /// <summary>
-    /// https://github.com/dotnet/runtime/issues/30524#issuecomment-524619972.
-    /// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys.
-    /// </summary>
-    internal sealed class JsonNonStringKeyDictionaryConverterFactory : JsonConverterFactory
-    {
-        /// <summary>
-        /// Only convert objects that implement IDictionary and do not have string keys.
-        /// </summary>
-        /// <param name="typeToConvert">Type convert.</param>
-        /// <returns>Conversion ability.</returns>
-        public override bool CanConvert(Type typeToConvert)
-        {
-            if (!typeToConvert.IsGenericType)
-            {
-                return false;
-            }
-
-            // Let built in converter handle string keys
-            if (typeToConvert.GenericTypeArguments[0] == typeof(string))
-            {
-                return false;
-            }
-
-            // Only support objects that implement IDictionary
-            return typeToConvert.GetInterface(nameof(IDictionary)) != null;
-        }
-
-        /// <summary>
-        /// Create converter for generic dictionary type.
-        /// </summary>
-        /// <param name="typeToConvert">Type to convert.</param>
-        /// <param name="options">Json serializer options.</param>
-        /// <returns>JsonConverter for given type.</returns>
-        public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
-        {
-            var converterType = typeof(JsonNonStringKeyDictionaryConverter<,>)
-                .MakeGenericType(typeToConvert.GenericTypeArguments[0], typeToConvert.GenericTypeArguments[1]);
-            var converter = (JsonConverter)Activator.CreateInstance(
-                converterType,
-                BindingFlags.Instance | BindingFlags.Public,
-                null,
-                null,
-                CultureInfo.CurrentCulture);
-            return converter;
-        }
-    }
-}

+ 0 - 60
MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs

@@ -1,60 +0,0 @@
-using System;
-using System.Buffers;
-using System.Buffers.Text;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace MediaBrowser.Common.Json.Converters
-{
-    /// <summary>
-    /// Converts a nullable int32 object or value to/from JSON.
-    /// </summary>
-    public class JsonNullableInt32Converter : JsonConverter<int?>
-    {
-        /// <inheritdoc />
-        public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
-        {
-            if (reader.TokenType == JsonTokenType.Null)
-            {
-                return null;
-            }
-
-            if (reader.TokenType == JsonTokenType.String)
-            {
-                ReadOnlySpan<byte> 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();
-        }
-
-        /// <inheritdoc />
-        public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options)
-        {
-            if (value is null)
-            {
-                writer.WriteNullValue();
-            }
-            else
-            {
-                writer.WriteNumberValue(value.Value);
-            }
-        }
-    }
-}

+ 0 - 75
MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs

@@ -1,75 +0,0 @@
-using System;
-using System.Buffers;
-using System.Buffers.Text;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace MediaBrowser.Common.Json.Converters
-{
-    /// <summary>
-    /// Parse JSON string as nullable long.
-    /// Javascript does not support 64-bit integers.
-    /// </summary>
-    public class JsonNullableInt64Converter : JsonConverter<long?>
-    {
-        /// <summary>
-        /// Read JSON string as int64.
-        /// </summary>
-        /// <param name="reader"><see cref="Utf8JsonReader"/>.</param>
-        /// <param name="type">Type.</param>
-        /// <param name="options">Options.</param>
-        /// <returns>Parsed value.</returns>
-        public override long? Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
-        {
-            if (reader.TokenType == JsonTokenType.Null)
-            {
-                return null;
-            }
-
-            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();
-        }
-
-        /// <summary>
-        /// Write long to JSON long.
-        /// </summary>
-        /// <param name="writer"><see cref="Utf8JsonWriter"/>.</param>
-        /// <param name="value">Value to write.</param>
-        /// <param name="options">Options.</param>
-        public override void Write(Utf8JsonWriter writer, long? value, JsonSerializerOptions options)
-        {
-            if (value is null)
-            {
-                writer.WriteNullValue();
-            }
-            else
-            {
-                writer.WriteNumberValue(value.Value);
-            }
-        }
-    }
-}

+ 2 - 7
MediaBrowser.Common/Json/JsonDefaults.cs

@@ -25,17 +25,12 @@ namespace MediaBrowser.Common.Json
             {
             {
                 ReadCommentHandling = JsonCommentHandling.Disallow,
                 ReadCommentHandling = JsonCommentHandling.Disallow,
                 WriteIndented = false,
                 WriteIndented = false,
-                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
+                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
+                NumberHandling = JsonNumberHandling.AllowReadingFromString
             };
             };
 
 
             options.Converters.Add(new JsonGuidConverter());
             options.Converters.Add(new JsonGuidConverter());
-            options.Converters.Add(new JsonInt32Converter());
-            options.Converters.Add(new JsonNullableInt32Converter());
             options.Converters.Add(new JsonStringEnumConverter());
             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;
             return options;
         }
         }

+ 6 - 0
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs

@@ -12,6 +12,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Json;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.MediaEncoding.Probing;
 using MediaBrowser.MediaEncoding.Probing;
@@ -54,6 +55,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
         private readonly object _runningProcessesLock = new object();
         private readonly object _runningProcessesLock = new object();
         private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
         private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
 
 
+        // MediaEncoder is registered as a Singleton
+        private readonly JsonSerializerOptions _jsonSerializerOptions;
+
         private List<string> _encoders = new List<string>();
         private List<string> _encoders = new List<string>();
         private List<string> _decoders = new List<string>();
         private List<string> _decoders = new List<string>();
         private List<string> _hwaccels = new List<string>();
         private List<string> _hwaccels = new List<string>();
@@ -75,6 +79,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
             _localization = localization;
             _localization = localization;
             _encodingHelperFactory = encodingHelperFactory;
             _encodingHelperFactory = encodingHelperFactory;
             _startupOptionFFmpegPath = config.GetValue<string>(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty;
             _startupOptionFFmpegPath = config.GetValue<string>(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty;
+            _jsonSerializerOptions = JsonDefaults.GetOptions();
         }
         }
 
 
         private EncodingHelper EncodingHelper => _encodingHelperFactory.Value;
         private EncodingHelper EncodingHelper => _encodingHelperFactory.Value;
@@ -414,6 +419,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 {
                 {
                     result = await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(
                     result = await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(
                                         process.StandardOutput.BaseStream,
                                         process.StandardOutput.BaseStream,
+                                        _jsonSerializerOptions,
                                         cancellationToken: cancellationToken).ConfigureAwait(false);
                                         cancellationToken: cancellationToken).ConfigureAwait(false);
                 }
                 }
                 catch
                 catch

+ 0 - 1
MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs

@@ -133,7 +133,6 @@ namespace MediaBrowser.MediaEncoding.Probing
         /// </summary>
         /// </summary>
         /// <value>The bits_per_raw_sample.</value>
         /// <value>The bits_per_raw_sample.</value>
         [JsonPropertyName("bits_per_raw_sample")]
         [JsonPropertyName("bits_per_raw_sample")]
-        [JsonConverter(typeof(JsonInt32Converter))]
         public int BitsPerRawSample { get; set; }
         public int BitsPerRawSample { get; set; }
 
 
         /// <summary>
         /// <summary>

+ 2 - 1
tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs

@@ -1,6 +1,7 @@
 using System.IO;
 using System.IO;
 using System.Text.Json;
 using System.Text.Json;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using MediaBrowser.Common.Json;
 using MediaBrowser.MediaEncoding.Probing;
 using MediaBrowser.MediaEncoding.Probing;
 using Xunit;
 using Xunit;
 
 
@@ -15,7 +16,7 @@ namespace Jellyfin.MediaEncoding.Tests
             var path = Path.Join("Test Data", fileName);
             var path = Path.Join("Test Data", fileName);
             using (var stream = File.OpenRead(path))
             using (var stream = File.OpenRead(path))
             {
             {
-                await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream).ConfigureAwait(false);
+                await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream, JsonDefaults.GetOptions()).ConfigureAwait(false);
             }
             }
         }
         }
     }
     }