diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index d55670a61..f1899c2b5 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -98,6 +98,7 @@ + diff --git a/NzbDrone.Common/RestProvider.cs b/NzbDrone.Common/RestProvider.cs index 9b1823257..6964d4b87 100644 --- a/NzbDrone.Common/RestProvider.cs +++ b/NzbDrone.Common/RestProvider.cs @@ -2,9 +2,9 @@ using System.IO; using System.Net; using System.Text; -using Newtonsoft.Json; using NzbDrone.Common.Contract; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Serializer; namespace NzbDrone.Common { @@ -27,7 +27,7 @@ namespace NzbDrone.Common { try { - var json = JsonConvert.SerializeObject(message); + var json = message.ToJson(); var request = (HttpWebRequest)WebRequest.Create(url); request.Timeout = TIMEOUT; diff --git a/NzbDrone.Common/Serializer/IntConverter.cs b/NzbDrone.Common/Serializer/IntConverter.cs new file mode 100644 index 000000000..d30db4c74 --- /dev/null +++ b/NzbDrone.Common/Serializer/IntConverter.cs @@ -0,0 +1,39 @@ +using System; +using Newtonsoft.Json; + +namespace NzbDrone.Common.Serializer +{ + public class IntConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value == null) + { + writer.WriteNull(); + } + else + { + writer.WriteValue(value); + } + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (!CanConvert(objectType)) + { + throw new JsonSerializationException("Can't convert type " + existingValue.GetType().FullName + " to number"); + } + if (objectType == typeof(Int64)) + { + return Convert.ToInt64(reader.Value); + } + + return Convert.ToInt32(reader.Value); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(Int32) || objectType == typeof(Int64) || objectType == typeof(int); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Common/Serializer/Json.cs b/NzbDrone.Common/Serializer/Json.cs index 866776ec9..c6c4ded7e 100644 --- a/NzbDrone.Common/Serializer/Json.cs +++ b/NzbDrone.Common/Serializer/Json.cs @@ -8,42 +8,47 @@ namespace NzbDrone.Common.Serializer { public static class Json { - private static readonly JsonSerializer JsonNetSerializer; - + private static readonly JsonSerializer Serializer; + private static readonly JsonSerializerSettings SerializerSetting; static Json() { - JsonNetSerializer = new JsonSerializer() - { - DateTimeZoneHandling = DateTimeZoneHandling.Utc, - NullValueHandling = NullValueHandling.Ignore, - Formatting = Formatting.Indented, - DefaultValueHandling = DefaultValueHandling.Include, - ContractResolver = new CamelCasePropertyNamesContractResolver() - }; - - JsonNetSerializer.Converters.Add(new StringEnumConverter { CamelCaseText = true }); + SerializerSetting = new JsonSerializerSettings + { + DateTimeZoneHandling = DateTimeZoneHandling.Utc, + NullValueHandling = NullValueHandling.Ignore, + Formatting = Formatting.Indented, + DefaultValueHandling = DefaultValueHandling.Include, + ContractResolver = new CamelCasePropertyNamesContractResolver() + }; + + + SerializerSetting.Converters.Add(new StringEnumConverter { CamelCaseText = true }); + SerializerSetting.Converters.Add(new IntConverter()); + + Serializer = JsonSerializer.Create(SerializerSetting); + } - public static T Deserialize(string json) where T : class, new() + public static T Deserialize(string json) where T : new() { - return JsonConvert.DeserializeObject(json); + return JsonConvert.DeserializeObject(json, SerializerSetting); } public static object Deserialize(string json, Type type) { - return JsonConvert.DeserializeObject(json, type); + return JsonConvert.DeserializeObject(json, type, SerializerSetting); } public static string ToJson(this object obj) { - return JsonConvert.SerializeObject(obj); + return JsonConvert.SerializeObject(obj, SerializerSetting); } public static void Serialize(TModel model, TextWriter outputStream) { var jsonTextWriter = new JsonTextWriter(outputStream); - JsonNetSerializer.Serialize(jsonTextWriter, model); + Serializer.Serialize(jsonTextWriter, model); jsonTextWriter.Flush(); } diff --git a/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetProviderTests/DownloadNzbFixture.cs b/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetProviderTests/DownloadNzbFixture.cs index c897df251..2e042dca1 100644 --- a/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetProviderTests/DownloadNzbFixture.cs +++ b/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetProviderTests/DownloadNzbFixture.cs @@ -4,6 +4,7 @@ using FizzWare.NBuilder; using Moq; using NUnit.Framework; using NzbDrone.Common; +using NzbDrone.Common.Serializer; using NzbDrone.Core.Configuration; using NzbDrone.Core.Download.Clients.Nzbget; using NzbDrone.Core.Parser.Model; @@ -51,9 +52,16 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetProviderTests [Test] public void should_add_item_to_queue() { + + var command = new JsonRequest + { + Method = "appendurl", + Params = new object[] { "30.Rock.S01E01.Pilot.720p.hdtv.nzb", "TV", 50, false, "http://www.nzbdrone.com" } + }; + Mocker.GetMock() .Setup(s => s.PostCommand("192.168.5.55:6789", "nzbget", "pass", - It.Is(c => c.Equals("{\"method\":\"appendurl\",\"params\":[\"30.Rock.S01E01.Pilot.720p.hdtv.nzb\",\"TV\",50,false,\"http://www.nzbdrone.com\"]}")))) + It.Is(c => c.Equals(command.ToJson())))) .Returns("{\"version\": \"1.1\",\"result\": true}"); Mocker.Resolve().DownloadNzb(_remoteEpisode); diff --git a/NzbDrone.Core/Download/Clients/Nzbget/NzbgetClient.cs b/NzbDrone.Core/Download/Clients/Nzbget/NzbgetClient.cs index 144805113..ee94a2198 100644 --- a/NzbDrone.Core/Download/Clients/Nzbget/NzbgetClient.cs +++ b/NzbDrone.Core/Download/Clients/Nzbget/NzbgetClient.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; using NLog; using NzbDrone.Common; +using NzbDrone.Common.Serializer; using NzbDrone.Core.Configuration; using NzbDrone.Core.Parser.Model; @@ -36,11 +36,11 @@ namespace NzbDrone.Core.Download.Clients.Nzbget }; _logger.Info("Adding report [{0}] to the queue.", title); - var response = PostCommand(JsonConvert.SerializeObject(command)); + var response = PostCommand(command.ToJson()); CheckForError(response); - var success = JsonConvert.DeserializeObject(response).Result; + var success = Json.Deserialize(response).Result; _logger.Debug("Queue Response: [{0}]", success); } @@ -61,11 +61,11 @@ namespace NzbDrone.Core.Download.Clients.Nzbget Params = null }; - var response = PostCommand(JsonConvert.SerializeObject(command)); + var response = PostCommand(command.ToJson()); CheckForError(response); - var itmes = JsonConvert.DeserializeObject(response).QueueItems; + var itmes = Json.Deserialize(response).QueueItems; foreach (var nzbGetQueueItem in itmes) { @@ -101,11 +101,11 @@ namespace NzbDrone.Core.Download.Clients.Nzbget }; var address = String.Format(@"{0}:{1}", host, port); - var response = _httpProvider.PostCommand(address, username, password, JsonConvert.SerializeObject(command)); + var response = _httpProvider.PostCommand(address, username, password, command.ToJson()); CheckForError(response); - return JsonConvert.DeserializeObject(response); + return Json.Deserialize(response); } public virtual string Test(string host, int port, string username, string password) @@ -134,7 +134,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget private void CheckForError(string response) { - var result = JsonConvert.DeserializeObject(response); + var result = Json.Deserialize(response); if (result.Error != null) throw new ApplicationException(result.Error.ToString()); diff --git a/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdClient.cs b/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdClient.cs index 40a241a1c..7a6eac544 100644 --- a/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdClient.cs +++ b/NzbDrone.Core/Download/Clients/Sabnzbd/SabnzbdClient.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Web; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NLog; using NzbDrone.Common; using NzbDrone.Common.Cache; +using NzbDrone.Common.Serializer; using NzbDrone.Core.Configuration; using NzbDrone.Core.Parser.Model; using RestSharp; @@ -107,7 +107,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd CheckForError(response); - var sabQueue = JsonConvert.DeserializeObject(JObject.Parse(response).SelectToken("queue").ToString()).Items; + var sabQueue = Json.Deserialize(JObject.Parse(response).SelectToken("queue").ToString()).Items; var queueItems = new List(); @@ -134,7 +134,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd CheckForError(response); - var items = JsonConvert.DeserializeObject(JObject.Parse(response).SelectToken("history").ToString()).Items; + var items = Json.Deserialize(JObject.Parse(response).SelectToken("history").ToString()).Items; return items ?? new List(); } @@ -166,7 +166,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd if (String.IsNullOrWhiteSpace(response)) return new SabCategoryModel { categories = new List() }; - var categories = JsonConvert.DeserializeObject(response); + var categories = Json.Deserialize(response); return categories; } @@ -199,7 +199,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd if (String.IsNullOrWhiteSpace(response)) return null; - var version = JsonConvert.DeserializeObject(response); + var version = Json.Deserialize(response); return version; } @@ -232,7 +232,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd private void CheckForError(string response) { - var result = JsonConvert.DeserializeObject(response); + var result = Json.Deserialize(response); if (result.Status != null && result.Status.Equals("false", StringComparison.InvariantCultureIgnoreCase)) throw new ApplicationException(result.Error); diff --git a/NzbDrone.Core/Indexers/IndexerSettingProvider.cs b/NzbDrone.Core/Indexers/IndexerSettingProvider.cs index a0a0650c7..ab7da9e58 100644 --- a/NzbDrone.Core/Indexers/IndexerSettingProvider.cs +++ b/NzbDrone.Core/Indexers/IndexerSettingProvider.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using NzbDrone.Common.Serializer; namespace NzbDrone.Core.Indexers { @@ -25,7 +25,7 @@ namespace NzbDrone.Core.Indexers return new TSetting(); } - return JsonConvert.DeserializeObject(indexerDef.Settings); + return Json.Deserialize(indexerDef.Settings); } } } \ No newline at end of file diff --git a/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs b/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs index 2ee5d7443..53f4d8a58 100644 --- a/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs +++ b/NzbDrone.Core/Notifications/NotificationSettingsProvider.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using NzbDrone.Common.Serializer; namespace NzbDrone.Core.Notifications { @@ -25,7 +25,7 @@ namespace NzbDrone.Core.Notifications return new TSetting(); } - return JsonConvert.DeserializeObject(indexerDef.Settings); + return Json.Deserialize(indexerDef.Settings); } } } \ No newline at end of file diff --git a/NzbDrone.Core/Notifications/Xbmc/JsonApiProvider.cs b/NzbDrone.Core/Notifications/Xbmc/JsonApiProvider.cs index 1d7cb5377..aa06901d1 100644 --- a/NzbDrone.Core/Notifications/Xbmc/JsonApiProvider.cs +++ b/NzbDrone.Core/Notifications/Xbmc/JsonApiProvider.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Linq; using NLog; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NzbDrone.Common; +using NzbDrone.Common.Serializer; using NzbDrone.Core.Model.Xbmc; using NzbDrone.Core.Tv; @@ -72,7 +72,7 @@ namespace NzbDrone.Core.Notifications.Xbmc if (CheckForError(response)) return new List(); - var result = JsonConvert.DeserializeObject(response); + var result = Json.Deserialize(response); return result.Result; } @@ -97,7 +97,7 @@ namespace NzbDrone.Core.Notifications.Xbmc if (response.StartsWith("{\"error\"")) { - var error = JsonConvert.DeserializeObject(response); + var error = Json.Deserialize(response); var code = error.Error["code"]; var message = error.Error["message"]; @@ -159,7 +159,7 @@ namespace NzbDrone.Core.Notifications.Xbmc if (CheckForError(response)) return; _logger.Trace(" from response"); - var result = JsonConvert.DeserializeObject>(response); + var result = Json.Deserialize>(response); if (!result.Result.Equals("OK", StringComparison.InvariantCultureIgnoreCase)) { @@ -185,7 +185,7 @@ namespace NzbDrone.Core.Notifications.Xbmc if (CheckForError(response)) return new List(); - var result = JsonConvert.DeserializeObject(response); + var result = Json.Deserialize(response); var shows = result.Result.TvShows; return shows; diff --git a/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs b/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs index bbc8a237a..9444b79f0 100644 --- a/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs +++ b/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs @@ -1,12 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NLog; using NzbDrone.Common; using NzbDrone.Common.Instrumentation; -using NzbDrone.Core.Messaging; +using NzbDrone.Common.Serializer; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Tv; using NzbDrone.Core.Model.Xbmc; @@ -63,7 +62,7 @@ namespace NzbDrone.Core.Notifications.Xbmc var response = _httpProvider.PostCommand(settings.Address, settings.Username, settings.Password, postJson.ToString()); Logger.Trace("Getting version from response"); - var result = JsonConvert.DeserializeObject>(response); + var result = Json.Deserialize>(response); var versionObject = result.Result.Property("version"); @@ -71,7 +70,7 @@ namespace NzbDrone.Core.Notifications.Xbmc return new XbmcVersion((int)versionObject.Value); if (versionObject.Value.Type == JTokenType.Object) - return JsonConvert.DeserializeObject(versionObject.Value.ToString()); + return Json.Deserialize(versionObject.Value.ToString()); throw new InvalidCastException("Unknown Version structure!: " + versionObject); } diff --git a/NzbDrone.Libraries.Test/JsonTests/JsonFixture.cs b/NzbDrone.Libraries.Test/JsonTests/JsonFixture.cs index 19a663db4..951eaa4a1 100644 --- a/NzbDrone.Libraries.Test/JsonTests/JsonFixture.cs +++ b/NzbDrone.Libraries.Test/JsonTests/JsonFixture.cs @@ -1,3 +1,5 @@ +using System; +using FluentAssertions; using NUnit.Framework; using NzbDrone.Common.Serializer; using NzbDrone.Test.Common; @@ -9,15 +11,19 @@ namespace NzbDrone.Libraries.Test.JsonTests { public class TypeWithNumbers { - public int Id { get; set; } + public int Int32 { get; set; } + public Int64 Int64 { get; set; } + public int? nullableIntIsNull { get; set; } + public int? nullableWithValue { get; set; } } [Test] public void should_be_able_to_deserialize_numbers() { - var quality = new TypeWithNumbers { Id = 12 }; + var quality = new TypeWithNumbers { Int32 = Int32.MaxValue, Int64 = Int64.MaxValue, nullableWithValue = 12 }; + var result = Json.Deserialize(quality.ToJson()); - Json.Deserialize(quality.ToJson()); + result.ShouldHave().AllProperties().EqualTo(quality); } } } diff --git a/NzbDrone.Libraries.Test/NzbDrone.Libraries.Test.csproj b/NzbDrone.Libraries.Test/NzbDrone.Libraries.Test.csproj index 11d3bbdc2..14c492823 100644 --- a/NzbDrone.Libraries.Test/NzbDrone.Libraries.Test.csproj +++ b/NzbDrone.Libraries.Test/NzbDrone.Libraries.Test.csproj @@ -33,6 +33,14 @@ MinimumRecommendedRules.ruleset + + False + ..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll + + + False + ..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll + ..\packages\NUnit.2.6.2\lib\nunit.framework.dll @@ -65,9 +73,7 @@ NzbDrone.Test.Common - - - +