mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-17 17:14:18 +02:00
New: Use System.Text.Json for Nancy and SignalR
Co-Authored-By: ta264 <ta264@users.noreply.github.com>
This commit is contained in:
@@ -127,10 +127,5 @@ namespace NzbDrone.Common.Serializer
|
||||
Serializer.Serialize(jsonTextWriter, model);
|
||||
jsonTextWriter.Flush();
|
||||
}
|
||||
|
||||
public static void Serialize<TModel>(TModel model, Stream outputStream)
|
||||
{
|
||||
Serialize(model, new StreamWriter(outputStream));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NzbDrone.Common.Serializer
|
||||
{
|
||||
public class PolymorphicWriteOnlyJsonConverter<T> : JsonConverter<T>
|
||||
{
|
||||
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return JsonSerializer.Deserialize<T>(ref reader, options);
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
|
||||
{
|
||||
JsonSerializer.Serialize(writer, value, value.GetType(), options);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Common.Serializer
|
||||
{
|
||||
public class STJHttpUriConverter : JsonConverter<HttpUri>
|
||||
{
|
||||
public override HttpUri Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return new HttpUri(reader.GetString());
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, HttpUri value, JsonSerializerOptions options)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteStringValue(value.FullUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Converters
|
||||
namespace NzbDrone.Common.Serializer
|
||||
{
|
||||
public class TimeSpanConverter : JsonConverter<TimeSpan>
|
||||
public class STJTimeSpanConverter : JsonConverter<TimeSpan>
|
||||
{
|
||||
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NzbDrone.Common.Serializer
|
||||
{
|
||||
public class STJUtcConverter : JsonConverter<DateTime>
|
||||
{
|
||||
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return DateTime.Parse(reader.GetString());
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NzbDrone.Common.Serializer
|
||||
{
|
||||
public class STJVersionConverter : JsonConverter<Version>
|
||||
{
|
||||
public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
try
|
||||
{
|
||||
Version v = new Version(reader.GetString());
|
||||
return v;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new JsonException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteStringValue(value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
88
src/NzbDrone.Common/Serializer/System.Text.Json/STJson.cs
Normal file
88
src/NzbDrone.Common/Serializer/System.Text.Json/STJson.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NzbDrone.Common.Serializer
|
||||
{
|
||||
public static class STJson
|
||||
{
|
||||
private static readonly JsonSerializerOptions SerializerSettings = GetSerializerSettings();
|
||||
private static readonly JsonWriterOptions WriterOptions = new JsonWriterOptions
|
||||
{
|
||||
Indented = true
|
||||
};
|
||||
|
||||
public static JsonSerializerOptions GetSerializerSettings()
|
||||
{
|
||||
var serializerSettings = new JsonSerializerOptions
|
||||
{
|
||||
AllowTrailingCommas = true,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
WriteIndented = true
|
||||
};
|
||||
|
||||
serializerSettings.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, true));
|
||||
serializerSettings.Converters.Add(new STJVersionConverter());
|
||||
serializerSettings.Converters.Add(new STJHttpUriConverter());
|
||||
serializerSettings.Converters.Add(new STJTimeSpanConverter());
|
||||
serializerSettings.Converters.Add(new STJUtcConverter());
|
||||
|
||||
return serializerSettings;
|
||||
}
|
||||
|
||||
public static T Deserialize<T>(string json)
|
||||
where T : new()
|
||||
{
|
||||
return JsonSerializer.Deserialize<T>(json, SerializerSettings);
|
||||
}
|
||||
|
||||
public static object Deserialize(string json, Type type)
|
||||
{
|
||||
return JsonSerializer.Deserialize(json, type, SerializerSettings);
|
||||
}
|
||||
|
||||
public static object Deserialize(Stream input, Type type)
|
||||
{
|
||||
return JsonSerializer.DeserializeAsync(input, type, SerializerSettings).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public static bool TryDeserialize<T>(string json, out T result)
|
||||
where T : new()
|
||||
{
|
||||
try
|
||||
{
|
||||
result = Deserialize<T>(json);
|
||||
return true;
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
result = default(T);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToJson(object obj)
|
||||
{
|
||||
return JsonSerializer.Serialize(obj, SerializerSettings);
|
||||
}
|
||||
|
||||
public static void Serialize<TModel>(TModel model, Stream outputStream, JsonSerializerOptions options = null)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
options = SerializerSettings;
|
||||
}
|
||||
|
||||
// Cast to object to get all properties written out
|
||||
// https://github.com/dotnet/corefx/issues/38650
|
||||
using (var writer = new Utf8JsonWriter(outputStream, options: WriterOptions))
|
||||
{
|
||||
JsonSerializer.Serialize(writer, (object)model, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@ using System.Data;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Dapper;
|
||||
using NzbDrone.Common.Serializer;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Converters
|
||||
{
|
||||
@@ -22,8 +23,8 @@ namespace NzbDrone.Core.Datastore.Converters
|
||||
};
|
||||
|
||||
serializerSettings.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, true));
|
||||
serializerSettings.Converters.Add(new TimeSpanConverter());
|
||||
serializerSettings.Converters.Add(new UtcConverter());
|
||||
serializerSettings.Converters.Add(new STJTimeSpanConverter());
|
||||
serializerSettings.Converters.Add(new STJUtcConverter());
|
||||
serializerSettings.Converters.Add(new DictionaryStringObjectJsonConverter());
|
||||
|
||||
SerializerSettings = serializerSettings;
|
||||
|
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Dapper;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Converters
|
||||
@@ -18,17 +16,4 @@ namespace NzbDrone.Core.Datastore.Converters
|
||||
return DateTime.SpecifyKind((DateTime)value, DateTimeKind.Utc);
|
||||
}
|
||||
}
|
||||
|
||||
public class UtcConverter : JsonConverter<DateTime>
|
||||
{
|
||||
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return DateTime.Parse(reader.GetString());
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
|
||||
@@ -15,6 +16,7 @@ namespace NzbDrone.Core.Datastore
|
||||
/// Allows a field to be lazy loaded.
|
||||
/// </summary>
|
||||
/// <typeparam name="TChild"></typeparam>
|
||||
[JsonConverter(typeof(LazyLoadedConverterFactory))]
|
||||
public class LazyLoaded<TChild> : ILazyLoaded
|
||||
{
|
||||
protected TChild _value;
|
||||
@@ -62,11 +64,6 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
return MemberwiseClone();
|
||||
}
|
||||
|
||||
public bool ShouldSerializeValue()
|
||||
{
|
||||
return IsLoaded;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
90
src/NzbDrone.Core/Datastore/LazyLoadedConverterFactory.cs
Normal file
90
src/NzbDrone.Core/Datastore/LazyLoadedConverterFactory.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public class LazyLoadedConverterFactory : JsonConverterFactory
|
||||
{
|
||||
public override bool CanConvert(Type typeToConvert)
|
||||
{
|
||||
if (!typeToConvert.IsGenericType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return typeToConvert.GetGenericTypeDefinition() == typeof(LazyLoaded<>);
|
||||
}
|
||||
|
||||
public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options)
|
||||
{
|
||||
var childType = type.GetGenericArguments()[0];
|
||||
|
||||
return (JsonConverter)Activator.CreateInstance(
|
||||
typeof(LazyLoadedConverter<>).MakeGenericType(childType),
|
||||
BindingFlags.Instance | BindingFlags.Public,
|
||||
binder: null,
|
||||
args: new object[] { options },
|
||||
culture: null);
|
||||
}
|
||||
|
||||
private class LazyLoadedConverter<TChild> : JsonConverter<LazyLoaded<TChild>>
|
||||
{
|
||||
private readonly JsonConverter<TChild> _childConverter;
|
||||
private readonly Type _childType;
|
||||
|
||||
public LazyLoadedConverter(JsonSerializerOptions options)
|
||||
{
|
||||
// For performance, use the existing converter if available.
|
||||
_childConverter = (JsonConverter<TChild>)options
|
||||
.GetConverter(typeof(TChild));
|
||||
|
||||
// Cache the type.
|
||||
_childType = typeof(TChild);
|
||||
}
|
||||
|
||||
public override LazyLoaded<TChild> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
TChild value;
|
||||
if (_childConverter != null)
|
||||
{
|
||||
reader.Read();
|
||||
value = _childConverter.Read(ref reader, _childType, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = JsonSerializer.Deserialize<TChild>(ref reader, options);
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
return new LazyLoaded<TChild>(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, LazyLoaded<TChild> value, JsonSerializerOptions options)
|
||||
{
|
||||
if (value.IsLoaded)
|
||||
{
|
||||
if (_childConverter != null)
|
||||
{
|
||||
_childConverter.Write(writer, value.Value, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
JsonSerializer.Serialize(writer, value.Value, options);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteNullValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,7 +1,10 @@
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using NzbDrone.Common.Serializer;
|
||||
|
||||
namespace NzbDrone.Core.Messaging.Commands
|
||||
{
|
||||
[JsonConverter(typeof(PolymorphicWriteOnlyJsonConverter<Command>))]
|
||||
public abstract class Command
|
||||
{
|
||||
private bool _sendUpdatesToClient;
|
||||
|
@@ -1,9 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Dapper;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Reflection;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Datastore.Converters;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
@@ -29,8 +30,8 @@ namespace NzbDrone.Core.ThingiProvider
|
||||
};
|
||||
|
||||
serializerSettings.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, true));
|
||||
serializerSettings.Converters.Add(new TimeSpanConverter());
|
||||
serializerSettings.Converters.Add(new UtcConverter());
|
||||
serializerSettings.Converters.Add(new STJTimeSpanConverter());
|
||||
serializerSettings.Converters.Add(new STJUtcConverter());
|
||||
serializerSettings.Converters.Add(new DictionaryStringObjectJsonConverter());
|
||||
|
||||
_serializerSettings = serializerSettings;
|
||||
|
@@ -5,7 +5,6 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Owin" Version="5.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="5.0.3" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="1.7.0" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
@@ -107,9 +107,9 @@ namespace Prowlarr.Host
|
||||
{
|
||||
services
|
||||
.AddSignalR()
|
||||
.AddNewtonsoftJsonProtocol(options =>
|
||||
.AddJsonProtocol(options =>
|
||||
{
|
||||
options.PayloadSerializerSettings = Json.GetSerializerSettings();
|
||||
options.PayloadSerializerOptions = STJson.GetSerializerSettings();
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
|
@@ -18,6 +18,7 @@ using Prowlarr.Api.V1.Config;
|
||||
using Prowlarr.Api.V1.History;
|
||||
using Prowlarr.Api.V1.Tags;
|
||||
using RestSharp;
|
||||
using RestSharp.Serializers.SystemTextJson;
|
||||
|
||||
namespace NzbDrone.Integration.Test
|
||||
{
|
||||
@@ -79,6 +80,7 @@ namespace NzbDrone.Integration.Test
|
||||
RestClient = new RestClient(RootUrl + "api/v1/");
|
||||
RestClient.AddDefaultHeader("Authentication", ApiKey);
|
||||
RestClient.AddDefaultHeader("X-Api-Key", ApiKey);
|
||||
RestClient.UseSystemTextJson();
|
||||
|
||||
Commands = new CommandClient(RestClient, ApiKey);
|
||||
History = new ClientBase<HistoryResource>(RestClient, ApiKey);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
|
||||
namespace NzbDrone.SignalR
|
||||
|
@@ -9,6 +9,7 @@
|
||||
<PackageReference Include="NLog" Version="4.7.7" />
|
||||
<PackageReference Include="NUnit" Version="3.13.1" />
|
||||
<PackageReference Include="RestSharp" Version="106.11.7" />
|
||||
<PackageReference Include="RestSharp.Serializers.SystemTextJson" Version="106.11.7" />
|
||||
<PackageReference Include="Unity" Version="5.11.10" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@@ -2,7 +2,7 @@ using NzbDrone.Core.Applications;
|
||||
|
||||
namespace Prowlarr.Api.V1.Application
|
||||
{
|
||||
public class ApplicationResource : ProviderResource
|
||||
public class ApplicationResource : ProviderResource<ApplicationResource>
|
||||
{
|
||||
public ApplicationSyncLevel SyncLevel { get; set; }
|
||||
public string TestCommand { get; set; }
|
||||
|
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using Prowlarr.Http.REST;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.CustomFilters;
|
||||
@@ -10,7 +11,7 @@ namespace Prowlarr.Api.V1.CustomFilters
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public string Label { get; set; }
|
||||
public List<dynamic> Filters { get; set; }
|
||||
public List<ExpandoObject> Filters { get; set; }
|
||||
}
|
||||
|
||||
public static class CustomFilterResourceMapper
|
||||
@@ -27,7 +28,7 @@ namespace Prowlarr.Api.V1.CustomFilters
|
||||
Id = model.Id,
|
||||
Type = model.Type,
|
||||
Label = model.Label,
|
||||
Filters = Json.Deserialize<List<dynamic>>(model.Filters)
|
||||
Filters = STJson.Deserialize<List<ExpandoObject>>(model.Filters)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -43,7 +44,7 @@ namespace Prowlarr.Api.V1.CustomFilters
|
||||
Id = resource.Id,
|
||||
Type = resource.Type,
|
||||
Label = resource.Label,
|
||||
Filters = Json.ToJson(resource.Filters)
|
||||
Filters = STJson.ToJson(resource.Filters)
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using Prowlarr.Http.REST;
|
||||
|
||||
@@ -12,8 +10,7 @@ namespace Prowlarr.Api.V1.Indexers
|
||||
{
|
||||
public int? LimitsMax { get; set; }
|
||||
public int? LimitsDefault { get; set; }
|
||||
|
||||
public List<IndexerCategory> Categories;
|
||||
public List<IndexerCategory> Categories { get; set; }
|
||||
}
|
||||
|
||||
public static class IndexerCapabilitiesResourceMapper
|
||||
|
@@ -8,7 +8,7 @@ using Prowlarr.Http.ClientSchema;
|
||||
|
||||
namespace Prowlarr.Api.V1.Indexers
|
||||
{
|
||||
public class IndexerResource : ProviderResource
|
||||
public class IndexerResource : ProviderResource<IndexerResource>
|
||||
{
|
||||
public string BaseUrl { get; set; }
|
||||
public bool Enable { get; set; }
|
||||
|
@@ -2,7 +2,7 @@ using NzbDrone.Core.Notifications;
|
||||
|
||||
namespace Prowlarr.Api.V1.Notifications
|
||||
{
|
||||
public class NotificationResource : ProviderResource
|
||||
public class NotificationResource : ProviderResource<NotificationResource>
|
||||
{
|
||||
public string Link { get; set; }
|
||||
public bool OnHealthIssue { get; set; }
|
||||
|
@@ -14,7 +14,7 @@ namespace Prowlarr.Api.V1
|
||||
public abstract class ProviderModuleBase<TProviderResource, TProvider, TProviderDefinition> : ProwlarrRestModule<TProviderResource>
|
||||
where TProviderDefinition : ProviderDefinition, new()
|
||||
where TProvider : IProvider
|
||||
where TProviderResource : ProviderResource, new()
|
||||
where TProviderResource : ProviderResource<TProviderResource>, new()
|
||||
{
|
||||
protected readonly IProviderFactory<TProvider, TProviderDefinition> _providerFactory;
|
||||
protected readonly ProviderResourceMapper<TProviderResource, TProviderDefinition> _resourceMapper;
|
||||
@@ -124,12 +124,9 @@ namespace Prowlarr.Api.V1
|
||||
var providerResource = _resourceMapper.ToResource(providerDefinition);
|
||||
var presetDefinitions = _providerFactory.GetPresetDefinitions(providerDefinition);
|
||||
|
||||
providerResource.Presets = presetDefinitions.Select(v =>
|
||||
{
|
||||
var presetResource = _resourceMapper.ToResource(v);
|
||||
|
||||
return presetResource as ProviderResource;
|
||||
}).ToList();
|
||||
providerResource.Presets = presetDefinitions
|
||||
.Select(v => _resourceMapper.ToResource(v))
|
||||
.ToList();
|
||||
|
||||
result.Add(providerResource);
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ using Prowlarr.Http.REST;
|
||||
|
||||
namespace Prowlarr.Api.V1
|
||||
{
|
||||
public class ProviderResource : RestResource
|
||||
public class ProviderResource<T> : RestResource
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public List<Field> Fields { get; set; }
|
||||
@@ -17,11 +17,11 @@ namespace Prowlarr.Api.V1
|
||||
public ProviderMessage Message { get; set; }
|
||||
public HashSet<int> Tags { get; set; }
|
||||
|
||||
public List<ProviderResource> Presets { get; set; }
|
||||
public List<T> Presets { get; set; }
|
||||
}
|
||||
|
||||
public class ProviderResourceMapper<TProviderResource, TProviderDefinition>
|
||||
where TProviderResource : ProviderResource, new()
|
||||
where TProviderResource : ProviderResource<TProviderResource>, new()
|
||||
where TProviderDefinition : ProviderDefinition, new()
|
||||
{
|
||||
public virtual TProviderResource ToResource(TProviderDefinition definition)
|
||||
|
@@ -8,7 +8,6 @@
|
||||
<PackageReference Include="Nancy" Version="2.0.0" />
|
||||
<PackageReference Include="Nancy.Authentication.Basic" Version="2.0.0" />
|
||||
<PackageReference Include="Nancy.Authentication.Forms" Version="2.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="NLog" Version="4.7.7" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Core.Update;
|
||||
using Prowlarr.Http.REST;
|
||||
|
||||
@@ -9,7 +8,6 @@ namespace Prowlarr.Api.V1.Update
|
||||
{
|
||||
public class UpdateResource : RestResource
|
||||
{
|
||||
[JsonConverter(typeof(Newtonsoft.Json.Converters.VersionConverter))]
|
||||
public Version Version { get; set; }
|
||||
|
||||
public string Branch { get; set; }
|
||||
|
@@ -2,10 +2,11 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text.Json;
|
||||
using NzbDrone.Common.EnsureThat;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Reflection;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Annotations;
|
||||
|
||||
namespace Prowlarr.Http.ClientSchema
|
||||
@@ -221,9 +222,9 @@ namespace Prowlarr.Http.ClientSchema
|
||||
{
|
||||
return fieldValue =>
|
||||
{
|
||||
if (fieldValue.GetType() == typeof(JArray))
|
||||
if (fieldValue is JsonElement e && e.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
return ((JArray)fieldValue).Select(s => s.Value<int>());
|
||||
return e.EnumerateArray().Select(s => s.GetInt32());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -235,9 +236,9 @@ namespace Prowlarr.Http.ClientSchema
|
||||
{
|
||||
return fieldValue =>
|
||||
{
|
||||
if (fieldValue.GetType() == typeof(JArray))
|
||||
if (fieldValue is JsonElement e && e.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
return ((JArray)fieldValue).Select(s => s.Value<string>());
|
||||
return e.EnumerateArray().Select(s => s.GetString());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -247,7 +248,18 @@ namespace Prowlarr.Http.ClientSchema
|
||||
}
|
||||
else
|
||||
{
|
||||
return fieldValue => fieldValue;
|
||||
return fieldValue =>
|
||||
{
|
||||
var element = fieldValue as JsonElement?;
|
||||
|
||||
if (element == null || !element.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var json = element.Value.GetRawText();
|
||||
return STJson.Deserialize(json, propertyType);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Data.SQLite;
|
||||
using FluentValidation;
|
||||
using Nancy;
|
||||
using Nancy.Extensions;
|
||||
using Nancy.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Exceptions;
|
||||
@@ -26,7 +28,10 @@ namespace Prowlarr.Http.ErrorManagement
|
||||
|
||||
if (exception is ApiException apiException)
|
||||
{
|
||||
_logger.Warn(apiException, "API Error");
|
||||
_logger.Warn(apiException, "API Error:\n{0}", apiException.Message);
|
||||
var body = RequestStream.FromStream(context.Request.Body).AsString();
|
||||
_logger.Trace("Request body:\n{0}", body);
|
||||
|
||||
return apiException.ToErrorResponse(context);
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using Nancy;
|
||||
using Nancy.Responses.Negotiation;
|
||||
using NzbDrone.Common.Serializer;
|
||||
@@ -8,6 +9,13 @@ namespace Prowlarr.Http.Extensions
|
||||
{
|
||||
public class NancyJsonSerializer : ISerializer
|
||||
{
|
||||
protected readonly JsonSerializerOptions _serializerSettings;
|
||||
|
||||
public NancyJsonSerializer()
|
||||
{
|
||||
_serializerSettings = STJson.GetSerializerSettings();
|
||||
}
|
||||
|
||||
public bool CanSerialize(MediaRange contentType)
|
||||
{
|
||||
return contentType == "application/json";
|
||||
@@ -15,7 +23,7 @@ namespace Prowlarr.Http.Extensions
|
||||
|
||||
public void Serialize<TModel>(MediaRange contentType, TModel model, Stream outputStream)
|
||||
{
|
||||
Json.Serialize(model, outputStream);
|
||||
STJson.Serialize(model, outputStream, _serializerSettings);
|
||||
}
|
||||
|
||||
public IEnumerable<string> Extensions { get; private set; }
|
||||
|
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Nancy;
|
||||
@@ -27,10 +27,8 @@ namespace Prowlarr.Http.Extensions
|
||||
|
||||
public static object FromJson(this Stream body, Type type)
|
||||
{
|
||||
var reader = new StreamReader(body, true);
|
||||
body.Position = 0;
|
||||
var value = reader.ReadToEnd();
|
||||
return Json.Deserialize(value, type);
|
||||
return STJson.Deserialize(body, type);
|
||||
}
|
||||
|
||||
public static JsonResponse<TModel> AsResponse<TModel>(this TModel model, NancyContext context, HttpStatusCode statusCode = HttpStatusCode.OK)
|
||||
|
@@ -7,7 +7,6 @@
|
||||
<PackageReference Include="Nancy" Version="2.0.0" />
|
||||
<PackageReference Include="Nancy.Authentication.Basic" Version="2.0.0" />
|
||||
<PackageReference Include="Nancy.Authentication.Forms" Version="2.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="NLog" Version="4.7.7" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Nancy;
|
||||
using Nancy.Responses.Negotiation;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using Prowlarr.Http.Extensions;
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace Prowlarr.Http.REST
|
||||
{
|
||||
resource = Request.Body.FromJson<TResource>();
|
||||
}
|
||||
catch (JsonReaderException e)
|
||||
catch (JsonException e)
|
||||
{
|
||||
throw new BadRequestException($"Invalid request body. {e.Message}");
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Prowlarr.Http.REST
|
||||
{
|
||||
public abstract class RestResource
|
||||
{
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
||||
public virtual int Id { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
|
Reference in New Issue
Block a user