mirror of https://github.com/lidarr/Lidarr
Fixed: Error deserializing preferred words with dapper
Fixes Sentry LIDARR-106 Fixes Sentry LIDARR-10B
This commit is contained in:
parent
2a4b3d79b8
commit
0f5531af4d
|
@ -0,0 +1,47 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Data.SQLite;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Datastore.Converters;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore.Converters
|
||||
{
|
||||
[TestFixture]
|
||||
public class KeyValuePairConverterFixture : CoreTest<EmbeddedDocumentConverter<List<KeyValuePair<string, int>>>>
|
||||
{
|
||||
private SQLiteParameter _param;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_param = new SQLiteParameter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_serialize_in_camel_case()
|
||||
{
|
||||
var items = new List<KeyValuePair<string, int>>
|
||||
{
|
||||
new KeyValuePair<string, int>("word", 1)
|
||||
};
|
||||
|
||||
Subject.SetValue(_param, items);
|
||||
|
||||
var result = (string)_param.Value;
|
||||
result.Should().Be(@"[
|
||||
{
|
||||
""key"": ""word"",
|
||||
""value"": 1
|
||||
}
|
||||
]");
|
||||
}
|
||||
|
||||
[TestCase(@"[{""key"": ""deluxe"", ""value"": 10 }]")]
|
||||
[TestCase(@"[{""Key"": ""deluxe"", ""Value"": 10 }]")]
|
||||
public void should_deserialize_case_insensitive(string input)
|
||||
{
|
||||
Subject.Parse(input).Should().BeEquivalentTo(new List<KeyValuePair<string, int>> { new KeyValuePair<string, int>("deluxe", 10) });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ namespace NzbDrone.Core.Datastore.Converters
|
|||
};
|
||||
|
||||
serializerSettings.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, true));
|
||||
serializerSettings.Converters.Add(new KeyValuePairConverter()); /* Remove in .NET 5 */
|
||||
serializerSettings.Converters.Add(new TimeSpanConverter());
|
||||
serializerSettings.Converters.Add(new UtcConverter());
|
||||
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Converters
|
||||
{
|
||||
/* See https://github.com/dotnet/runtime/issues/1197
|
||||
Can be removed once we switch to .NET 5
|
||||
Based on https://github.com/layomia/dotnet_runtime/blob/master/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/KeyValuePairConverter.cs
|
||||
and https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to
|
||||
*/
|
||||
|
||||
public class KeyValuePairConverter : JsonConverterFactory
|
||||
{
|
||||
public override bool CanConvert(Type typeToConvert)
|
||||
{
|
||||
if (!typeToConvert.IsGenericType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeToConvert.GetGenericTypeDefinition() != typeof(KeyValuePair<,>))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override JsonConverter CreateConverter(
|
||||
Type type,
|
||||
JsonSerializerOptions options)
|
||||
{
|
||||
var keyType = type.GetGenericArguments()[0];
|
||||
var valueType = type.GetGenericArguments()[1];
|
||||
|
||||
var converter = (JsonConverter)Activator.CreateInstance(
|
||||
typeof(KeyValuePairConverterInner<,>).MakeGenericType(
|
||||
new Type[] { keyType, valueType }),
|
||||
BindingFlags.Instance | BindingFlags.Public,
|
||||
binder: null,
|
||||
args: null,
|
||||
culture: null);
|
||||
|
||||
return converter;
|
||||
}
|
||||
|
||||
private class KeyValuePairConverterInner<TKey, TValue> :
|
||||
JsonConverter<KeyValuePair<TKey, TValue>>
|
||||
{
|
||||
public KeyValuePairConverterInner()
|
||||
{
|
||||
}
|
||||
|
||||
public override KeyValuePair<TKey, TValue> Read(
|
||||
ref Utf8JsonReader reader,
|
||||
Type typeToConvert,
|
||||
JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType != JsonTokenType.StartObject)
|
||||
{
|
||||
throw new JsonException();
|
||||
}
|
||||
|
||||
TKey k = default;
|
||||
var keySet = false;
|
||||
|
||||
TValue v = default;
|
||||
var valueSet = false;
|
||||
|
||||
reader.Read();
|
||||
|
||||
// Get the first property.
|
||||
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||
{
|
||||
throw new JsonException();
|
||||
}
|
||||
|
||||
var propertyName = reader.GetString();
|
||||
if (string.Equals(propertyName, "Key", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reader.Read();
|
||||
k = JsonSerializer.Deserialize<TKey>(ref reader, options);
|
||||
keySet = true;
|
||||
}
|
||||
else if (string.Equals(propertyName, "Value", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reader.Read();
|
||||
v = JsonSerializer.Deserialize<TValue>(ref reader, options);
|
||||
valueSet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonException();
|
||||
}
|
||||
|
||||
// Get the second property.
|
||||
reader.Read();
|
||||
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||
{
|
||||
throw new JsonException();
|
||||
}
|
||||
|
||||
propertyName = reader.GetString();
|
||||
if (!keySet && string.Equals(propertyName, "Key", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reader.Read();
|
||||
k = JsonSerializer.Deserialize<TKey>(ref reader, options);
|
||||
}
|
||||
else if (!valueSet && string.Equals(propertyName, "Value", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reader.Read();
|
||||
v = JsonSerializer.Deserialize<TValue>(ref reader, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonException();
|
||||
}
|
||||
|
||||
reader.Read();
|
||||
|
||||
if (reader.TokenType != JsonTokenType.EndObject)
|
||||
{
|
||||
throw new JsonException();
|
||||
}
|
||||
|
||||
return new KeyValuePair<TKey, TValue>(k, v);
|
||||
}
|
||||
|
||||
public override void Write(
|
||||
Utf8JsonWriter writer,
|
||||
KeyValuePair<TKey, TValue> kvp,
|
||||
JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
|
||||
writer.WritePropertyName("key");
|
||||
JsonSerializer.Serialize(writer, kvp.Key, options);
|
||||
|
||||
writer.WritePropertyName("value");
|
||||
JsonSerializer.Serialize(writer, kvp.Value, options);
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue