Migrate from newtonsoft.json to system.text.json

This commit is contained in:
Zoe Roux 2024-03-22 21:20:47 +01:00
parent d7e5b8b916
commit ad9d1ee430
No known key found for this signature in database
4 changed files with 136 additions and 177 deletions

View File

@ -19,6 +19,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using AspNetCore.Proxy;
using Autofac;
using Kyoo.Abstractions;
@ -30,10 +32,6 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using JsonOptions = Kyoo.Core.Api.JsonOptions;
namespace Kyoo.Core
{
@ -86,7 +84,6 @@ namespace Kyoo.Core
public void Configure(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddTransient<IConfigureOptions<MvcNewtonsoftJsonOptions>, JsonOptions>();
services
.AddMvcCore(options =>
@ -96,10 +93,11 @@ namespace Kyoo.Core
options.ModelBinderProviders.Insert(0, new IncludeBinder.Provider());
options.ModelBinderProviders.Insert(0, new FilterBinder.Provider());
})
.AddNewtonsoftJson(x =>
.AddJsonOptions(x =>
{
x.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
x.SerializerSettings.Converters.Add(new StringEnumConverter());
x.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
x.JsonSerializerOptions.TypeInfoResolver = new PolymorphicTypeResolver();
x.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
})
.AddDataAnnotations()
.AddControllersAsServices()

View File

@ -1,55 +0,0 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
namespace Kyoo.Core.Api
{
/// <summary>
/// The custom options of newtonsoft json. This simply add the <see cref="PeopleRoleConverter"/> and set
/// the <see cref="JsonSerializerContract"/>. It is on a separate class to use dependency injection.
/// </summary>
public class JsonOptions : IConfigureOptions<MvcNewtonsoftJsonOptions>
{
/// <summary>
/// The http context accessor given to the <see cref="JsonSerializerContract"/>.
/// </summary>
private readonly IHttpContextAccessor _httpContextAccessor;
/// <summary>
/// Create a new <see cref="JsonOptions"/>.
/// </summary>
/// <param name="httpContextAccessor">
/// The http context accessor given to the <see cref="JsonSerializerContract"/>.
/// </param>
public JsonOptions(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
/// <inheritdoc />
public void Configure(MvcNewtonsoftJsonOptions options)
{
options.SerializerSettings.ContractResolver = new JsonSerializerContract(
_httpContextAccessor
);
}
}
}

View File

@ -1,117 +1,69 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
// // Kyoo - A portable and vast media library solution.
// // Copyright (c) Kyoo.
// //
// // See AUTHORS.md and LICENSE file in the project root for full license information.
// //
// // Kyoo is free software: you can redistribute it and/or modify
// // it under the terms of the GNU General Public License as published by
// // the Free Software Foundation, either version 3 of the License, or
// // any later version.
// //
// // Kyoo is distributed in the hope that it will be useful,
// // but WITHOUT ANY WARRANTY; without even the implied warranty of
// // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// // GNU General Public License for more details.
// //
// // You should have received a copy of the GNU General Public License
// // along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
// using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Net.Http.Formatting;
// using System.Reflection;
// using Kyoo.Abstractions.Models;
// using Kyoo.Abstractions.Models.Attributes;
// using Microsoft.AspNetCore.Http;
// using static System.Text.Json.JsonNamingPolicy;
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
// namespace Kyoo.Core.Api
// {
// /// <summary>
// /// A custom json serializer that respects <see cref="SerializeIgnoreAttribute"/> and
// /// <see cref="DeserializeIgnoreAttribute"/>. It also handle <see cref="LoadableRelationAttribute"/> via the
// /// <c>fields</c> query parameter and <see cref="IThumbnails"/> items.
// /// </summary>
// public class JsonSerializerContract(IHttpContextAccessor? httpContextAccessor, MediaTypeFormatter formatter)
// : JsonContractResolver(formatter)
// {
// /// <inheritdoc />
// protected override JsonProperty CreateProperty(
// MemberInfo member,
// MemberSerialization memberSerialization
// )
// {
// JsonProperty property = base.CreateProperty(member, memberSerialization);
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using static System.Text.Json.JsonNamingPolicy;
namespace Kyoo.Core.Api
{
/// <summary>
/// A custom json serializer that respects <see cref="SerializeIgnoreAttribute"/> and
/// <see cref="DeserializeIgnoreAttribute"/>. It also handle <see cref="LoadableRelationAttribute"/> via the
/// <c>fields</c> query parameter and <see cref="IThumbnails"/> items.
/// </summary>
public class JsonSerializerContract : CamelCasePropertyNamesContractResolver
{
/// <summary>
/// The http context accessor used to retrieve the <c>fields</c> query parameter as well as the type of
/// resource currently serializing.
/// </summary>
private readonly IHttpContextAccessor _httpContextAccessor;
/// <summary>
/// Create a new <see cref="JsonSerializerContract"/>.
/// </summary>
/// <param name="httpContextAccessor">The http context accessor to use.</param>
public JsonSerializerContract(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
/// <inheritdoc />
protected override JsonProperty CreateProperty(
MemberInfo member,
MemberSerialization memberSerialization
)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
LoadableRelationAttribute? relation =
member.GetCustomAttribute<LoadableRelationAttribute>();
if (relation != null)
{
property.ShouldSerialize = _ =>
{
if (
_httpContextAccessor.HttpContext!.Items["fields"]
is not ICollection<string> fields
)
return false;
return fields.Contains(member.Name);
};
}
return property;
}
protected override IList<JsonProperty> CreateProperties(
Type type,
MemberSerialization memberSerialization
)
{
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
if (
properties.All(x => x.PropertyName != "kind")
&& type.IsAssignableTo(typeof(IResource))
)
{
properties.Add(
new JsonProperty()
{
DeclaringType = type,
PropertyName = "kind",
UnderlyingName = "kind",
PropertyType = typeof(string),
ValueProvider = new FixedValueProvider(CamelCase.ConvertName(type.Name)),
Readable = true,
Writable = false,
TypeNameHandling = TypeNameHandling.None,
}
);
}
return properties;
}
public class FixedValueProvider(object value) : IValueProvider
{
public object GetValue(object target) => value;
public void SetValue(object target, object? value) =>
throw new NotImplementedException();
}
}
}
// LoadableRelationAttribute? relation =
// member.GetCustomAttribute<LoadableRelationAttribute>();
// if (relation != null)
// {
// if (httpContextAccessor != null)
// {
// property.ShouldSerialize = _ =>
// {
// if (
// httpContextAccessor.HttpContext!.Items["fields"]
// is not ICollection<string> fields
// )
// return false;
// return fields.Contains(member.Name);
// };
// }
// else
// property.ShouldSerialize = _ => true;
// }
// return property;
// }
// }
// }

View File

@ -0,0 +1,64 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using Kyoo.Abstractions.Models;
using static System.Text.Json.JsonNamingPolicy;
namespace Kyoo.Core.Api;
public class PolymorphicTypeResolver : DefaultJsonTypeInfoResolver
{
private static readonly IList<JsonDerivedType> _types = AppDomain
.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => p.IsAssignableTo(typeof(IResource)) && p.IsClass)
.Select(x => new JsonDerivedType(x, CamelCase.ConvertName(x.Name)))
.ToList();
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
{
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
if (
jsonTypeInfo.Type.IsAssignableTo(typeof(IResource))
&& jsonTypeInfo.Properties.All(x => x.Name != "kind")
)
{
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
{
TypeDiscriminatorPropertyName = "kind",
IgnoreUnrecognizedTypeDiscriminators = true,
UnknownDerivedTypeHandling =
JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor,
DerivedTypes = { },
};
Console.WriteLine(string.Join(",", _types.Select(x => x.DerivedType.Name)));
foreach (JsonDerivedType derived in _types)
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(derived);
}
return jsonTypeInfo;
}
}