mirror of https://github.com/Squidex/squidex.git
21 changed files with 339 additions and 57 deletions
@ -0,0 +1,135 @@ |
|||
// ==========================================================================
|
|||
// JsonInheritanceConverter.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using System.Runtime.Serialization; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using NJsonSchema.Annotations; |
|||
// ReSharper disable ConvertIfStatementToReturnStatement
|
|||
|
|||
namespace Squidex.Controllers.Api.Schemas.Models.Converters |
|||
{ |
|||
public sealed class JsonInheritanceConverter : JsonConverter |
|||
{ |
|||
private readonly string discriminator; |
|||
|
|||
[ThreadStatic] |
|||
private static bool isReading; |
|||
|
|||
[ThreadStatic] |
|||
private static bool isWriting; |
|||
|
|||
public override bool CanWrite |
|||
{ |
|||
get |
|||
{ |
|||
if (!isWriting) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
return isWriting = false; |
|||
} |
|||
} |
|||
|
|||
public override bool CanRead |
|||
{ |
|||
get |
|||
{ |
|||
if (!isReading) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
return isReading = false; |
|||
} |
|||
} |
|||
|
|||
public JsonInheritanceConverter(string discriminator) |
|||
{ |
|||
this.discriminator = discriminator; |
|||
} |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
isWriting = true; |
|||
try |
|||
{ |
|||
var jsonObject = JObject.FromObject(value, serializer); |
|||
|
|||
jsonObject.AddFirst(new JProperty(discriminator, GetSchemaName(value.GetType()))); |
|||
|
|||
writer.WriteToken(jsonObject.CreateReader()); |
|||
} |
|||
finally |
|||
{ |
|||
isWriting = false; |
|||
} |
|||
} |
|||
|
|||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
isReading = true; |
|||
try |
|||
{ |
|||
var jsonObject = serializer.Deserialize<JObject>(reader); |
|||
|
|||
var subName = jsonObject[discriminator]?.Value<string>(); |
|||
|
|||
if (subName == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var subType = GetObjectSubtype(objectType, subName); |
|||
|
|||
if (subType == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return serializer.Deserialize(jsonObject.CreateReader(), subType); |
|||
} |
|||
finally |
|||
{ |
|||
isReading = false; |
|||
} |
|||
} |
|||
|
|||
private static Type GetObjectSubtype(Type objectType, string discriminatorValue) |
|||
{ |
|||
var knownTypeAttribute = |
|||
objectType.GetTypeInfo().GetCustomAttributes<KnownTypeAttribute>() |
|||
.FirstOrDefault(a => IsKnownType(a, discriminatorValue)); |
|||
|
|||
return knownTypeAttribute?.Type; |
|||
} |
|||
|
|||
private static bool IsKnownType(KnownTypeAttribute attribute, string discriminator) |
|||
{ |
|||
var type = attribute.Type; |
|||
|
|||
return type != null && GetSchemaName(type) == discriminator; |
|||
} |
|||
|
|||
private static string GetSchemaName(Type type) |
|||
{ |
|||
var schenaName = type.GetTypeInfo().GetCustomAttribute<JsonSchemaAttribute>()?.Name; |
|||
|
|||
return schenaName ?? type.Name; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue