Fixing one to one relation null's serialization

This commit is contained in:
Zoe Roux 2021-03-06 22:26:39 +01:00
parent b907e45a08
commit 6bf6746320
9 changed files with 83 additions and 22 deletions

View File

@ -306,10 +306,13 @@ namespace Kyoo.Controllers
(Show s, nameof(Show.Collections)) => CollectionRepository
.GetAll(x => x.Shows.Any(y => y.ID == obj.ID))
.Then(x => s.Collections = x),
// TODO Studio loading does not work.
(Show s, nameof(Show.Studio)) => StudioRepository
.Get(x => x.Shows.Any(y => y.ID == obj.ID))
.Then(x => s.Studio = x),
.Then(x =>
{
s.Studio = x;
s.StudioID = x?.ID ?? 0;
}),
(Season s, nameof(Season.ExternalIDs)) => ProviderRepository
.GetMetadataID(x => x.SeasonID == obj.ID)
@ -319,7 +322,11 @@ namespace Kyoo.Controllers
.Then(x => s.Episodes = x),
(Season s, nameof(Season.Show)) => ShowRepository
.Get(x => x.Seasons.Any(y => y.ID == obj.ID))
.Then(x => s.Show = x),
.Then(x =>
{
s.Show = x;
s.ShowID = x?.ID ?? 0;
}),
(Episode e, nameof(Episode.ExternalIDs)) => ProviderRepository
.GetMetadataID(x => x.EpisodeID == obj.ID)
@ -329,14 +336,26 @@ namespace Kyoo.Controllers
.Then(x => e.Tracks = x),
(Episode e, nameof(Episode.Show)) => ShowRepository
.Get(x => x.Episodes.Any(y => y.ID == obj.ID))
.Then(x => e.Show = x),
.Then(x =>
{
e.Show = x;
e.ShowID = x?.ID ?? 0;
}),
(Episode e, nameof(Episode.Season)) => SeasonRepository
.Get(x => x.Episodes.Any(y => y.ID == e.ID))
.Then(x => e.Season = x),
.Then(x =>
{
e.Season = x;
e.SeasonID = x?.ID ?? 0;
}),
(Track t, nameof(Track.Episode)) => EpisodeRepository
.Get(x => x.Tracks.Any(y => y.ID == obj.ID))
.Then(x => t.Episode = x),
.Then(x =>
{
t.Episode = x;
t.EpisodeID = x?.ID ?? 0;
}),
(Genre g, nameof(Genre.Shows)) => ShowRepository
.GetAll(x => x.Genres.Any(y => y.ID == obj.ID))

View File

@ -4,7 +4,17 @@ namespace Kyoo.Models.Attributes
{
[AttributeUsage(AttributeTargets.Property, Inherited = false)]
public class EditableRelationAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Property)]
public class LoadableRelationAttribute : Attribute { }
public class LoadableRelationAttribute : Attribute
{
public string RelationID { get; }
public LoadableRelationAttribute() {}
public LoadableRelationAttribute(string relationID)
{
RelationID = relationID;
}
}
}

View File

@ -10,10 +10,10 @@ namespace Kyoo.Models
{
public int ID { get; set; }
public string Slug => Show != null ? GetSlug(Show.Slug, SeasonNumber, EpisodeNumber) : ID.ToString();
public int ShowID { get; set; }
[LoadableRelation] public virtual Show Show { get; set; }
public int? SeasonID { get; set; }
[LoadableRelation] public virtual Season Season { get; set; }
[SerializeIgnore] public int ShowID { get; set; }
[LoadableRelation(nameof(ShowID))] public virtual Show Show { get; set; }
[SerializeIgnore] public int? SeasonID { get; set; }
[LoadableRelation(nameof(SeasonID))] public virtual Season Season { get; set; }
public int SeasonNumber { get; set; } = -1;
public int EpisodeNumber { get; set; } = -1;

View File

@ -8,7 +8,7 @@ namespace Kyoo.Models
public class Season : IResource
{
public int ID { get; set; }
public int ShowID { get; set; }
[SerializeIgnore] public int ShowID { get; set; }
public int SeasonNumber { get; set; } = -1;
@ -21,7 +21,7 @@ namespace Kyoo.Models
public string Thumb => $"/api/seasons/{Slug}/thumb";
[EditableRelation] [LoadableRelation] public virtual ICollection<MetadataID> ExternalIDs { get; set; }
[LoadableRelation] public virtual Show Show { get; set; }
[LoadableRelation(nameof(ShowID))] public virtual Show Show { get; set; }
[LoadableRelation] public virtual ICollection<Episode> Episodes { get; set; }
public Season() { }

View File

@ -28,7 +28,7 @@ namespace Kyoo.Models
[SerializeIgnore] public int? StudioID { get; set; }
[LoadableRelation] [EditableRelation] public virtual Studio Studio { get; set; }
[LoadableRelation(nameof(StudioID))] [EditableRelation] public virtual Studio Studio { get; set; }
[LoadableRelation] [EditableRelation] public virtual ICollection<Genre> Genres { get; set; }
[LoadableRelation] [EditableRelation] public virtual ICollection<PeopleRole> People { get; set; }
[LoadableRelation] public virtual ICollection<Season> Seasons { get; set; }

View File

@ -57,7 +57,7 @@ namespace Kyoo.Models
public class Track : Stream, IResource
{
public int ID { get; set; }
public int EpisodeID { get; set; }
[SerializeIgnore] public int EpisodeID { get; set; }
public bool IsDefault
{
get => isDefault;
@ -114,11 +114,18 @@ namespace Kyoo.Models
}
public bool IsExternal { get; set; }
[LoadableRelation] public virtual Episode Episode { get; set; }
[LoadableRelation(nameof(EpisodeID))] public virtual Episode Episode { get; set; }
public Track() { }
public Track(StreamType type, string title, string language, bool isDefault, bool isForced, string codec, bool isExternal, string path)
public Track(StreamType type,
string title,
string language,
bool isDefault,
bool isForced,
string codec,
bool isExternal,
string path)
: base(title, language, codec, isDefault, isForced, path, type)
{
IsExternal = isExternal;

View File

@ -33,6 +33,20 @@ namespace Kyoo
: ex.Body as MemberExpression;
return member!.Member.Name;
}
public static object GetValue([NotNull] this MemberInfo member, [NotNull] object obj)
{
if (member == null)
throw new ArgumentNullException(nameof(member));
if (obj == null)
throw new ArgumentNullException(nameof(obj));
return member switch
{
PropertyInfo property => property.GetValue(obj),
FieldInfo field => field.GetValue(obj),
_ => throw new ArgumentException($"Can't get value of a non property/field (member: {member}).")
};
}
public static string ToSlug(string str)
{

View File

@ -10,9 +10,21 @@ namespace Kyoo.Controllers
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (member?.GetCustomAttribute<LoadableRelationAttribute>() != null)
property.NullValueHandling = NullValueHandling.Ignore;
LoadableRelationAttribute relation = member?.GetCustomAttribute<LoadableRelationAttribute>();
if (relation != null)
{
if (relation.RelationID == null)
property.ShouldSerialize = x => member.GetValue(x) != null;
else
property.ShouldSerialize = x =>
{
if (member.GetValue(x) != null)
return true;
return x.GetType().GetProperty(relation.RelationID)?.GetValue(x) != null;
};
}
if (member?.GetCustomAttribute<SerializeIgnoreAttribute>() != null)
property.ShouldSerialize = _ => false;
if (member?.GetCustomAttribute<DeserializeIgnoreAttribute>() != null)

View File

@ -75,7 +75,6 @@ namespace Kyoo.CommonApi
Type pageType = Utility.GetGenericDefinition(result.DeclaredType, typeof(Page<>));
// TODO loading is case sensitive. Maybe convert them in the first check.
if (pageType != null)
{
foreach (IResource resource in ((dynamic)result.Value).Items)