using System; using System.Buffers; using System.Collections.Generic; using System.Reflection; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace Kyoo.Controllers { public class JsonPropertySelector : CamelCasePropertyNamesContractResolver { private readonly Dictionary> _ignored; private readonly Dictionary> _forceSerialize; public JsonPropertySelector() { _ignored = new Dictionary>(); _forceSerialize = new Dictionary>(); } public JsonPropertySelector(Dictionary> ignored, Dictionary> forceSerialize) { _ignored = ignored ?? new Dictionary>(); _forceSerialize = forceSerialize ?? new Dictionary>(); } private bool IsIgnored(Type type, string propertyName) { if (_ignored.ContainsKey(type) && _ignored[type].Contains(propertyName)) return true; if (type.BaseType == null) return false; return _ignored.ContainsKey(type.BaseType) && _ignored[type.BaseType].Contains(propertyName); } private bool IsSerializationForced(Type type, string propertyName) { if (_forceSerialize.ContainsKey(type) && _forceSerialize[type].Contains(propertyName)) return true; if (type.BaseType == null) return false; return _forceSerialize.ContainsKey(type.BaseType) && _forceSerialize[type.BaseType].Contains(propertyName); } protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization); if (IsIgnored(property.DeclaringType, property.PropertyName)) { property.ShouldSerialize = i => false; property.Ignored = true; } else if (IsSerializationForced(property.DeclaringType, property.PropertyName)) { property.ShouldSerialize = i => true; property.Ignored = false; } return property; } } public class JsonDetailed : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext context) { if (context.Result is ObjectResult result) { result.Formatters.Add(new NewtonsoftJsonOutputFormatter( new JsonSerializerSettings { ContractResolver = new JsonPropertySelector(null, new Dictionary>() { {typeof(Show), new HashSet {"genres", "studio"}}, {typeof(Episode), new HashSet {"tracks"}}, {typeof(PeopleRole), new HashSet {"show"}} }) }, context.HttpContext.RequestServices.GetRequiredService>(), context.HttpContext.RequestServices.GetRequiredService>().Value)); } } } }