Serialization and deserialziation with polymorphism (#13762)
* Support polymophism when sending or receiving interfaces * Handle attempts to deserialize interfaces nicer * updated OpenApi.json * Update src/Umbraco.Cms.Api.Common/Json/NamedSystemTextJsonInputFormatter.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Cms.Api.Management/ManagementApiComposer.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Cms.Api.Management/OpenApi/ConfigureUmbracoSwaggerGenOptions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Infrastructure/Serialization/UmbracoJsonTypeInfoResolver.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Infrastructure/Serialization/UmbracoJsonTypeInfoResolver.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Infrastructure/Serialization/UmbracoJsonTypeInfoResolver.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Infrastructure/Serialization/UmbracoJsonTypeInfoResolver.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Infrastructure/Serialization/UmbracoJsonTypeInfoResolver.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Infrastructure/Serialization/UmbracoJsonTypeInfoResolver.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Infrastructure/Serialization/UmbracoJsonTypeInfoResolver.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Infrastructure/Serialization/UmbracoJsonTypeInfoResolver.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Invert to avoid nesting * Updated OpenApi.json * Update schema --------- Co-authored-by: Mole <nikolajlauridsen@protonmail.ch>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Serialization;
|
||||
|
||||
public interface IUmbracoJsonTypeInfoResolver : IJsonTypeInfoResolver
|
||||
{
|
||||
IEnumerable<Type> FindSubTypes(Type type);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Serialization;
|
||||
|
||||
public sealed class UmbracoJsonTypeInfoResolver : DefaultJsonTypeInfoResolver, IUmbracoJsonTypeInfoResolver
|
||||
{
|
||||
private readonly ITypeFinder _typeFinder;
|
||||
private readonly ConcurrentDictionary<Type, ISet<Type>> _subTypesCache = new ConcurrentDictionary<Type, ISet<Type>>();
|
||||
|
||||
public UmbracoJsonTypeInfoResolver(ITypeFinder typeFinder)
|
||||
{
|
||||
_typeFinder = typeFinder;
|
||||
}
|
||||
|
||||
public IEnumerable<Type> FindSubTypes(Type type)
|
||||
{
|
||||
if (_subTypesCache.TryGetValue(type, out ISet<Type>? cachedResult))
|
||||
{
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
var result = _typeFinder.FindClassesOfType(type).ToHashSet();
|
||||
_subTypesCache.TryAdd(type, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
|
||||
{
|
||||
JsonTypeInfo result = base.GetTypeInfo(type, options);
|
||||
|
||||
if (!type.IsInterface)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
Type[] subTypes = FindSubTypes(type).ToArray();
|
||||
|
||||
if (!subTypes.Any())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
JsonPolymorphismOptions jsonPolymorphismOptions = result.PolymorphismOptions ?? new JsonPolymorphismOptions();
|
||||
|
||||
IEnumerable<Type> knownSubTypes = jsonPolymorphismOptions.DerivedTypes.Select(x => x.DerivedType);
|
||||
IEnumerable<Type> subTypesToAdd = subTypes.Except(knownSubTypes);
|
||||
foreach (Type subType in subTypesToAdd)
|
||||
{
|
||||
jsonPolymorphismOptions.DerivedTypes.Add(new JsonDerivedType(
|
||||
subType,
|
||||
subType.Name ?? string.Empty));
|
||||
}
|
||||
|
||||
result.PolymorphismOptions = jsonPolymorphismOptions;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user