From 5f64ab02a01f35f2bc2429cdee56973e77048fa5 Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 25 Aug 2020 07:33:58 -0600 Subject: [PATCH 1/6] bump System.Text.Json --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 3 --- Jellyfin.Api/Controllers/PluginsController.cs | 8 ++++++-- Jellyfin.Api/Helpers/MediaInfoHelper.cs | 6 +++++- Jellyfin.Api/Jellyfin.Api.csproj | 1 + Jellyfin.Data/Jellyfin.Data.csproj | 1 + .../Extensions/ApiServiceCollectionExtensions.cs | 2 +- Jellyfin.Server/Jellyfin.Server.csproj | 1 + .../Migrations/Routines/MigrateDisplayPreferencesDb.cs | 5 +++++ Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs | 7 ++++++- .../Json/Converters/JsonNullableInt32Converter.cs | 5 +++++ .../Json/Converters/JsonNullableInt64Converter.cs | 5 +++++ MediaBrowser.Common/Json/JsonDefaults.cs | 2 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- .../MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj | 1 + 14 files changed, 39 insertions(+), 10 deletions(-) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 48e2f5d4a..5bf740cfc 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -90,9 +90,6 @@ namespace Emby.Server.Implementations.Data _typeMapper = new TypeMapper(); _jsonOptions = JsonDefaults.GetOptions(); - // GetItem throws NotSupportedException with this enabled, so hardcode false. - _jsonOptions.IgnoreNullValues = false; - DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); } diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index b2f34680b..a82f2621a 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -120,10 +120,14 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - var configuration = (BasePluginConfiguration)await JsonSerializer.DeserializeAsync(Request.Body, plugin.ConfigurationType, _serializerOptions) + var configuration = (BasePluginConfiguration?)await JsonSerializer.DeserializeAsync(Request.Body, plugin.ConfigurationType, _serializerOptions) .ConfigureAwait(false); - plugin.UpdateConfiguration(configuration); + if (configuration != null) + { + plugin.UpdateConfiguration(configuration); + } + return NoContent(); } diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index d2d1855a4..3a736d1e8 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -127,7 +127,11 @@ namespace Jellyfin.Api.Helpers { // Since we're going to be setting properties on MediaSourceInfos that come out of _mediaSourceManager, we should clone it // Should we move this directly into MediaSourceManager? - result.MediaSources = JsonSerializer.Deserialize(JsonSerializer.SerializeToUtf8Bytes(mediaSources)); + var mediaSourcesClone = JsonSerializer.Deserialize(JsonSerializer.SerializeToUtf8Bytes(mediaSources)); + if (mediaSourcesClone != null) + { + result.MediaSources = mediaSourcesClone; + } result.PlaySessionId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); } diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 24bc07b66..7eb0ba007 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -19,6 +19,7 @@ + diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 43b838cc1..bf5833ae4 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -22,6 +22,7 @@ + diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 1f9fc7078..ddbe0edb7 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -168,7 +168,7 @@ namespace Jellyfin.Server.Extensions // From JsonDefaults options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling; options.JsonSerializerOptions.WriteIndented = jsonOptions.WriteIndented; - options.JsonSerializerOptions.IgnoreNullValues = jsonOptions.IgnoreNullValues; + options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition; options.JsonSerializerOptions.Converters.Clear(); foreach (var converter in jsonOptions.Converters) diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 7541707d9..4cc51a098 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -54,6 +54,7 @@ + diff --git a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs index b15ccf01e..2e5f0cc05 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs @@ -81,6 +81,11 @@ namespace Jellyfin.Server.Migrations.Routines foreach (var result in results) { var dto = JsonSerializer.Deserialize(result[3].ToString(), _jsonOptions); + if (dto is null) + { + continue; + } + var chromecastVersion = dto.CustomPrefs.TryGetValue("chromecastVersion", out var version) ? chromecastDict[version] : ChromecastVersion.Stable; diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs index 274e6ab73..6cd6d1f82 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs @@ -74,7 +74,12 @@ namespace Jellyfin.Server.Migrations.Routines foreach (var entry in queryResult) { - UserMockup mockup = JsonSerializer.Deserialize(entry[2].ToBlob(), JsonDefaults.GetOptions()); + UserMockup? mockup = JsonSerializer.Deserialize(entry[2].ToBlob(), JsonDefaults.GetOptions()); + if (mockup is null) + { + continue; + } + var userDataDir = Path.Combine(_paths.UserConfigurationDirectoryPath, mockup.Name); var config = File.Exists(Path.Combine(userDataDir, "config.xml")) diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs index c1660fe76..9db44d626 100644 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs +++ b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs @@ -14,6 +14,11 @@ namespace MediaBrowser.Common.Json.Converters /// public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + if (reader.TokenType == JsonTokenType.Null) + { + return null; + } + if (reader.TokenType == JsonTokenType.String) { ReadOnlySpan span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs index 53e5f6e9d..a9cdc23d7 100644 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs +++ b/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs @@ -21,6 +21,11 @@ namespace MediaBrowser.Common.Json.Converters /// Parsed value. 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 diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index 891715b3d..b46ecffc7 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Common.Json { ReadCommentHandling = JsonCommentHandling.Disallow, WriteIndented = false, - IgnoreNullValues = true + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }; options.Converters.Add(new JsonGuidConverter()); diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 902e29b20..a2aef948b 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -25,7 +25,7 @@ - + diff --git a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj index a4ef10648..9d797e8ee 100644 --- a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj +++ b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj @@ -10,6 +10,7 @@ + From acd88dae45e87189a485d898bf3e4c6367cfff99 Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 25 Aug 2020 08:11:50 -0600 Subject: [PATCH 2/6] fix build --- .../HttpServer/WebSocketConnection.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index d738047e0..dedc8978b 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -179,7 +179,7 @@ namespace Emby.Server.Implementations.HttpServer return; } - WebSocketMessage stub; + WebSocketMessage? stub; try { @@ -209,6 +209,12 @@ namespace Emby.Server.Implementations.HttpServer return; } + if (stub is null) + { + _logger.LogError("Error processing web socket message"); + return; + } + // Tell the PipeReader how much of the buffer we have consumed reader.AdvanceTo(buffer.End); From 582c016d3bb967dad6100e4ff9c5d84317e2edc5 Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 25 Aug 2020 21:19:55 -0600 Subject: [PATCH 3/6] bump to preview8 and remove extra references --- Jellyfin.Api/Jellyfin.Api.csproj | 1 - Jellyfin.Data/Jellyfin.Data.csproj | 1 - Jellyfin.Server/Jellyfin.Server.csproj | 1 - MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 7eb0ba007..24bc07b66 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -19,7 +19,6 @@ - diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index bf5833ae4..43b838cc1 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -22,7 +22,6 @@ - diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 4cc51a098..7541707d9 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -54,7 +54,6 @@ - diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index a2aef948b..8854caa2e 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -25,7 +25,7 @@ - + diff --git a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj index 9d797e8ee..a4ef10648 100644 --- a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj +++ b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj @@ -10,7 +10,6 @@ - From 8b96881aa1667495c78b0955321254da0dc5a22f Mon Sep 17 00:00:00 2001 From: crobibero Date: Wed, 26 Aug 2020 08:22:48 -0600 Subject: [PATCH 4/6] Clean up json Converters --- .../ApiServiceCollectionExtensions.cs | 1 + .../Json/Converters/JsonDoubleConverter.cs | 56 ------------- .../Json/Converters/JsonInt32Converter.cs | 40 --------- .../Json/Converters/JsonInt64Converter.cs | 56 ------------- .../JsonNonStringKeyDictionaryConverter.cs | 82 ------------------- ...nNonStringKeyDictionaryConverterFactory.cs | 59 ------------- .../Converters/JsonNullableInt32Converter.cs | 60 -------------- .../Converters/JsonNullableInt64Converter.cs | 75 ----------------- MediaBrowser.Common/Json/JsonDefaults.cs | 9 +- .../Encoder/MediaEncoder.cs | 6 ++ .../Probing/MediaStreamInfo.cs | 1 - .../FFprobeParserTests.cs | 3 +- 12 files changed, 11 insertions(+), 437 deletions(-) delete mode 100644 MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index ddbe0edb7..0fd599cfc 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -169,6 +169,7 @@ namespace Jellyfin.Server.Extensions options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling; options.JsonSerializerOptions.WriteIndented = jsonOptions.WriteIndented; options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition; + options.JsonSerializerOptions.NumberHandling = jsonOptions.NumberHandling; options.JsonSerializerOptions.Converters.Clear(); foreach (var converter in jsonOptions.Converters) diff --git a/MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs b/MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs deleted file mode 100644 index 56c0ecbe9..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs +++ /dev/null @@ -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 -{ - /// - /// Double to String JSON converter. - /// Web client send quoted doubles. - /// - public class JsonDoubleConverter : JsonConverter - { - /// - /// Read JSON string as double. - /// - /// . - /// Type. - /// Options. - /// Parsed value. - 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(); - } - - /// - /// Write double to JSON string. - /// - /// . - /// Value to write. - /// Options. - public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options) - { - writer.WriteNumberValue(value); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs deleted file mode 100644 index 7ed9d6766..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs +++ /dev/null @@ -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 -{ - /// - /// Converts a int32 object or value to/from JSON. - /// - public class JsonInt32Converter : 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; - } - - if (int.TryParse(reader.GetString(), out number)) - { - return number; - } - } - - return reader.GetInt32(); - } - - /// - public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) - { - writer.WriteNumberValue(value); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs b/MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs deleted file mode 100644 index 427f1fa7e..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs +++ /dev/null @@ -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 -{ - /// - /// Parse JSON string as long. - /// Javascript does not support 64-bit integers. - /// - public class JsonInt64Converter : 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; - } - - // 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(); - } - - /// - /// Write long to JSON long. - /// - /// . - /// Value to write. - /// Options. - public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options) - { - writer.WriteNumberValue(value); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs b/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs deleted file mode 100644 index 8053461f0..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs +++ /dev/null @@ -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 -{ - /// - /// Converter for Dictionaries without string key. - /// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys. - /// - /// Type of key. - /// Type of value. - internal sealed class JsonNonStringKeyDictionaryConverter : JsonConverter> - { - /// - /// Read JSON. - /// - /// The Utf8JsonReader. - /// The type to convert. - /// The json serializer options. - /// Typed dictionary. - /// Dictionary key type not supported. - public override IDictionary 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)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 is not supported."); - } - - while (enumerator.MoveNext()) - { - var element = (KeyValuePair)enumerator.Current; - instance.Add((TKey)parse.Invoke(null, new[] { (object?)element.Key }), element.Value); - } - - return instance; - } - - /// - /// Write dictionary as Json. - /// - /// The Utf8JsonWriter. - /// The dictionary value. - /// The Json serializer options. - public override void Write(Utf8JsonWriter writer, IDictionary value, JsonSerializerOptions options) - { - var convertedDictionary = new Dictionary(value.Count); - foreach (var (k, v) in value) - { - if (k != null) - { - convertedDictionary[k.ToString()] = v; - } - } - - JsonSerializer.Serialize(writer, convertedDictionary, options); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs b/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs deleted file mode 100644 index 52f360740..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs +++ /dev/null @@ -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 -{ - /// - /// https://github.com/dotnet/runtime/issues/30524#issuecomment-524619972. - /// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys. - /// - internal sealed class JsonNonStringKeyDictionaryConverterFactory : JsonConverterFactory - { - /// - /// Only convert objects that implement IDictionary and do not have string keys. - /// - /// Type convert. - /// Conversion ability. - 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; - } - - /// - /// Create converter for generic dictionary type. - /// - /// Type to convert. - /// Json serializer options. - /// JsonConverter for given type. - 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; - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs deleted file mode 100644 index 9db44d626..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs +++ /dev/null @@ -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 -{ - /// - /// Converts a nullable int32 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.Null) - { - return null; - } - - 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 deleted file mode 100644 index a9cdc23d7..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs +++ /dev/null @@ -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 -{ - /// - /// 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.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(); - } - - /// - /// 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 b46ecffc7..9d30927db 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -25,17 +25,12 @@ namespace MediaBrowser.Common.Json { ReadCommentHandling = JsonCommentHandling.Disallow, WriteIndented = false, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + NumberHandling = JsonNumberHandling.AllowReadingFromString }; 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; } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 9d01da40f..5a3a9185d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -12,6 +12,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; @@ -54,6 +55,9 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly object _runningProcessesLock = new object(); private readonly List _runningProcesses = new List(); + // MediaEncoder is registered as a Singleton + private readonly JsonSerializerOptions _jsonSerializerOptions; + private List _encoders = new List(); private List _decoders = new List(); private List _hwaccels = new List(); @@ -75,6 +79,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _localization = localization; _encodingHelperFactory = encodingHelperFactory; _startupOptionFFmpegPath = config.GetValue(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty; + _jsonSerializerOptions = JsonDefaults.GetOptions(); } private EncodingHelper EncodingHelper => _encodingHelperFactory.Value; @@ -414,6 +419,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { result = await JsonSerializer.DeserializeAsync( process.StandardOutput.BaseStream, + _jsonSerializerOptions, cancellationToken: cancellationToken).ConfigureAwait(false); } catch diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index 8996d3b09..b7b23deff 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -133,7 +133,6 @@ namespace MediaBrowser.MediaEncoding.Probing /// /// The bits_per_raw_sample. [JsonPropertyName("bits_per_raw_sample")] - [JsonConverter(typeof(JsonInt32Converter))] public int BitsPerRawSample { get; set; } /// diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs index 2032f6cec..c39ef0ce9 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs @@ -1,6 +1,7 @@ using System.IO; using System.Text.Json; using System.Threading.Tasks; +using MediaBrowser.Common.Json; using MediaBrowser.MediaEncoding.Probing; using Xunit; @@ -15,7 +16,7 @@ namespace Jellyfin.MediaEncoding.Tests var path = Path.Join("Test Data", fileName); using (var stream = File.OpenRead(path)) { - await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false); + await JsonSerializer.DeserializeAsync(stream, JsonDefaults.GetOptions()).ConfigureAwait(false); } } } From 78ae86b86a66855374c1e604118756abdfffe3f9 Mon Sep 17 00:00:00 2001 From: crobibero Date: Wed, 26 Aug 2020 08:23:35 -0600 Subject: [PATCH 5/6] Apply suggestions from code review --- .../Migrations/Routines/MigrateDisplayPreferencesDb.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs index 2e5f0cc05..7f57358ec 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs @@ -81,7 +81,7 @@ namespace Jellyfin.Server.Migrations.Routines foreach (var result in results) { var dto = JsonSerializer.Deserialize(result[3].ToString(), _jsonOptions); - if (dto is null) + if (dto == null) { continue; } From de4cfa223498dde4e665c452337f032c29270abe Mon Sep 17 00:00:00 2001 From: crobibero Date: Wed, 26 Aug 2020 08:45:59 -0600 Subject: [PATCH 6/6] Apply suggestions from code review --- Emby.Server.Implementations/HttpServer/WebSocketConnection.cs | 2 +- Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index dedc8978b..7eae4e764 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -209,7 +209,7 @@ namespace Emby.Server.Implementations.HttpServer return; } - if (stub is null) + if (stub == null) { _logger.LogError("Error processing web socket message"); return; diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs index 6cd6d1f82..ac6890f38 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs @@ -75,7 +75,7 @@ namespace Jellyfin.Server.Migrations.Routines foreach (var entry in queryResult) { UserMockup? mockup = JsonSerializer.Deserialize(entry[2].ToBlob(), JsonDefaults.GetOptions()); - if (mockup is null) + if (mockup == null) { continue; }