From 6ddbe8420f6bc61b2561c20def326fa1b4291c5e Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 24 Dec 2020 08:10:30 -0700 Subject: [PATCH] Add tests for special Omdb json --- .../JsonOmdbNotAvailableConverterFactory.cs | 36 +++++++++++++++++ .../JsonOmdbNotAvailableStringConverter.cs | 33 +++++++++++++++ .../JsonOmdbNotAvailableStructConverter.cs | 35 ++++++++++++++++ .../Plugins/Omdb/OmdbProvider.cs | 40 +++++++++++++++++-- .../Jellyfin.Common.Tests.csproj | 1 + .../Json/JsonOmdbConverterTests.cs | 21 ++++++++++ 6 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableConverterFactory.cs create mode 100644 MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs create mode 100644 MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStructConverter.cs create mode 100644 tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs diff --git a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableConverterFactory.cs b/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableConverterFactory.cs new file mode 100644 index 0000000000..5994ce9226 --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableConverterFactory.cs @@ -0,0 +1,36 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// + /// Json Omdb converter factory. + /// + /// + /// Remove when Omdb is moved to plugin. + /// + public class JsonOmdbNotAvailableConverterFactory : JsonConverterFactory + { + /// + public override bool CanConvert(Type typeToConvert) + { + return (typeToConvert.IsGenericType + && typeToConvert.GetGenericTypeDefinition() == typeof(Nullable<>) + && typeToConvert.GenericTypeArguments[0].IsValueType) + || typeToConvert == typeof(string); + } + + /// + public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + if (typeToConvert == typeof(string)) + { + return (JsonConverter)Activator.CreateInstance(typeof(JsonOmdbNotAvailableStringConverter)); + } + + var structType = typeToConvert.GenericTypeArguments[0]; + return (JsonConverter)Activator.CreateInstance(typeof(JsonOmdbNotAvailableStructConverter<>).MakeGenericType(structType)); + } + } +} diff --git a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs b/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs new file mode 100644 index 0000000000..2b343a5059 --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// + /// Converts a string N/A to string.Empty. + /// + public class JsonOmdbNotAvailableStringConverter : JsonConverter + { + /// + public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + var str = reader.GetString(); + if (str != null && str.Equals("N/A", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + } + + return JsonSerializer.Deserialize(ref reader, options); + } + + /// + public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) + { + JsonSerializer.Serialize(value, options); + } + } +} diff --git a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStructConverter.cs b/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStructConverter.cs new file mode 100644 index 0000000000..b9e67ce2de --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStructConverter.cs @@ -0,0 +1,35 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// + /// Converts a string N/A to string.Empty. + /// + /// The resulting type. + public class JsonOmdbNotAvailableStructConverter : JsonConverter + where T : struct + { + /// + public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + var str = reader.GetString(); + if (str != null && str.Equals("N/A", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + } + + return JsonSerializer.Deserialize(ref reader, options); + } + + /// + public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options) + { + JsonSerializer.Serialize(value, options); + } + } +} diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 3c21629990..1ebd1b13a3 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -8,10 +8,12 @@ using System.Linq; using System.Net.Http; using System.Text; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; using MediaBrowser.Common.Json; +using MediaBrowser.Common.Json.Converters; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -467,74 +469,104 @@ namespace MediaBrowser.Providers.Plugins.Omdb return string.Equals(lang, "en", StringComparison.OrdinalIgnoreCase); } - internal class SeasonRootObject + public class SeasonRootObject { + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Title { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string seriesID { get; set; } - public int Season { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] + public int? Season { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public int? totalSeasons { get; set; } public RootObject[] Episodes { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Response { get; set; } } - internal class RootObject + public class RootObject { + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Title { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Year { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Rated { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Released { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Runtime { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Genre { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Director { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Writer { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Actors { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Plot { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Language { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Country { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Awards { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Poster { get; set; } public List Ratings { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Metascore { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string imdbRating { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string imdbVotes { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string imdbID { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Type { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string DVD { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string BoxOffice { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Production { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Website { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] public string Response { get; set; } - public int Episode { get; set; } + [JsonConverter(typeof(JsonOmdbNotAvailableConverterFactory))] + public int? Episode { get; set; } public float? GetRottenTomatoScore() { diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index af4684f562..91b34546f3 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -29,6 +29,7 @@ + diff --git a/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs new file mode 100644 index 0000000000..90537dc1ff --- /dev/null +++ b/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs @@ -0,0 +1,21 @@ +using System.Text.Json; +using MediaBrowser.Common.Json; +using MediaBrowser.Providers.Plugins.Omdb; +using Xunit; + +namespace Jellyfin.Common.Tests.Json +{ + public static class JsonOmdbConverterTests + { + [Fact] + public static void Deserialize_Omdb_Response_Not_Available_Success() + { + const string Input = "{\"Title\":\"Chapter 1\",\"Year\":\"2013\",\"Rated\":\"TV-MA\",\"Released\":\"01 Feb 2013\",\"Season\":\"N/A\",\"Episode\":\"N/A\",\"Runtime\":\"55 min\",\"Genre\":\"Drama\",\"Director\":\"David Fincher\",\"Writer\":\"Michael Dobbs (based on the novels by), Andrew Davies (based on the mini-series by), Beau Willimon (created for television by), Beau Willimon, Sam Forman (staff writer)\",\"Actors\":\"Kevin Spacey, Robin Wright, Kate Mara, Corey Stoll\",\"Plot\":\"Congressman Francis Underwood has been declined the chair for Secretary of State. He's now gathering his own team to plot his revenge. Zoe Barnes, a reporter for the Washington Herald, will do anything to get her big break.\",\"Language\":\"English\",\"Country\":\"USA\",\"Awards\":\"N/A\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BMTY5MTU4NDQzNV5BMl5BanBnXkFtZTgwMzk2ODcxMzE@._V1_SX300.jpg\",\"Ratings\":[{\"Source\":\"Internet Movie Database\",\"Value\":\"8.7/10\"}],\"Metascore\":\"N/A\",\"imdbRating\":\"8.7\",\"imdbVotes\":\"6736\",\"imdbID\":\"tt2161930\",\"seriesID\":\"N/A\",\"Type\":\"episode\",\"Response\":\"True\"}"; + var seasonRootObject = JsonSerializer.Deserialize(Input, JsonDefaults.GetOptions()); + Assert.NotNull(seasonRootObject); + Assert.Null(seasonRootObject?.Awards); + Assert.Null(seasonRootObject?.Episode); + Assert.Null(seasonRootObject?.Metascore); + } + } +}