From 8201cd32e8895946d4c1b3dca1f08e00cffdc26c Mon Sep 17 00:00:00 2001 From: manuc66 Date: Fri, 1 Oct 2021 22:15:18 +0200 Subject: [PATCH 1/3] handle generic sub types --- JsonSubTypes.Tests/GenericTests.cs | 52 ++++++++++++++++++++++++++++++ JsonSubTypes/JsonSubtypes.cs | 20 ++++++++++-- 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 JsonSubTypes.Tests/GenericTests.cs diff --git a/JsonSubTypes.Tests/GenericTests.cs b/JsonSubTypes.Tests/GenericTests.cs new file mode 100644 index 0000000..9eaf8f4 --- /dev/null +++ b/JsonSubTypes.Tests/GenericTests.cs @@ -0,0 +1,52 @@ +using System; +using Newtonsoft.Json; +using NUnit.Framework; + +namespace JsonSubTypes.Tests +{[JsonConverter(typeof(JsonSubtypes), "Type")] + [JsonSubtypes.KnownSubType(typeof(Some<>), "Some")] + public interface IResult + { + string Type { get;} + } + + public class SomeInteger: Some { + public override string ResultType { get { return "SomeInteger"; }} + + } + + public class SomeText: Some { + public override string ResultType { get { return "SomeText"; }} + + } + + [JsonConverter(typeof(JsonSubtypes), "ResultType")] + //[JsonSubtypes.KnownSubType(typeof(SomeInteger), "SomeInteger")] + //[JsonSubtypes.KnownSubType(typeof(SomeText), "SomeText")] + public abstract class Some : IResult + { + + public string Type { get { return "Some"; }} + public abstract string ResultType { get; } + public T Value { get; set; } + } + + [TestFixture] + public class GenericTests + { + + + [Test] + public void DeserializingSubTypeWithDateParsesCorrectly() + { + var input = new SomeInteger {Value = 42}; + var json = JsonConvert.SerializeObject(input); + + Console.WriteLine(json); + + var result = JsonConvert.DeserializeObject(json); + + Console.WriteLine(result); + } + } +} diff --git a/JsonSubTypes/JsonSubtypes.cs b/JsonSubTypes/JsonSubtypes.cs index 3d7f04b..e7cbe0a 100644 --- a/JsonSubTypes/JsonSubtypes.cs +++ b/JsonSubTypes/JsonSubtypes.cs @@ -392,14 +392,30 @@ private static Type GetTypeByName(string typeName, TypeInfo parentType) typeByName = insideAssembly.GetType(searchLocation + typeName, false, true); } - var typeByNameInfo = ToTypeInfo(typeByName); - if (typeByNameInfo != null && parentType.IsAssignableFrom(typeByNameInfo)) + TypeInfo typeByNameInfo = ToTypeInfo(typeByName); + if (typeByNameInfo == null) + { + return null; + } + + if (parentType.IsAssignableFrom(typeByNameInfo) || parentType.IsGenericType && IsSubclassOfRawGeneric(parentType, typeByNameInfo)) { return typeByName; } return null; } + + static bool IsSubclassOfRawGeneric(TypeInfo generic, TypeInfo toCheck) { + while (toCheck != null && toCheck != typeof(object)) { + TypeInfo cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck; + if (generic == cur) { + return true; + } + toCheck = toCheck.BaseType; + } + return false; + } private static Type GetTypeFromMapping(NullableDictionary typeMapping, JToken discriminatorToken, JsonSerializer serializer) { From 57c592cdd339a07e22a9ac338c29410febef25a2 Mon Sep 17 00:00:00 2001 From: Emmanuel Counasse Date: Fri, 22 Oct 2021 22:18:33 +0200 Subject: [PATCH 2/3] fix compilation with other frameworks --- JsonSubTypes/JsonSubtypes.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/JsonSubTypes/JsonSubtypes.cs b/JsonSubTypes/JsonSubtypes.cs index e7cbe0a..8dbbced 100644 --- a/JsonSubTypes/JsonSubtypes.cs +++ b/JsonSubTypes/JsonSubtypes.cs @@ -398,7 +398,7 @@ private static Type GetTypeByName(string typeName, TypeInfo parentType) return null; } - if (parentType.IsAssignableFrom(typeByNameInfo) || parentType.IsGenericType && IsSubclassOfRawGeneric(parentType, typeByNameInfo)) + if (parentType.IsAssignableFrom(typeByNameInfo) || (parentType.IsGenericType && IsSubclassOfRawGeneric(parentType, typeByNameInfo))) { return typeByName; } @@ -407,12 +407,13 @@ private static Type GetTypeByName(string typeName, TypeInfo parentType) } static bool IsSubclassOfRawGeneric(TypeInfo generic, TypeInfo toCheck) { - while (toCheck != null && toCheck != typeof(object)) { - TypeInfo cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck; + TypeInfo objectTypeInfo = ToTypeInfo(typeof(object)); + while (toCheck != null && toCheck != objectTypeInfo) { + TypeInfo cur = toCheck.IsGenericType ? ToTypeInfo(toCheck.GetGenericTypeDefinition()) : toCheck; if (generic == cur) { return true; } - toCheck = toCheck.BaseType; + toCheck = ToTypeInfo(toCheck.BaseType); } return false; } From 668c0e6e8f48afe501f30d79c0fdf48e285567ef Mon Sep 17 00:00:00 2001 From: Emmanuel Counasse Date: Fri, 22 Oct 2021 22:44:17 +0200 Subject: [PATCH 3/3] simplify loop --- JsonSubTypes/JsonSubtypes.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/JsonSubTypes/JsonSubtypes.cs b/JsonSubTypes/JsonSubtypes.cs index 8dbbced..988fd60 100644 --- a/JsonSubTypes/JsonSubtypes.cs +++ b/JsonSubTypes/JsonSubtypes.cs @@ -407,15 +407,13 @@ private static Type GetTypeByName(string typeName, TypeInfo parentType) } static bool IsSubclassOfRawGeneric(TypeInfo generic, TypeInfo toCheck) { + TypeInfo cur = toCheck; TypeInfo objectTypeInfo = ToTypeInfo(typeof(object)); - while (toCheck != null && toCheck != objectTypeInfo) { - TypeInfo cur = toCheck.IsGenericType ? ToTypeInfo(toCheck.GetGenericTypeDefinition()) : toCheck; - if (generic == cur) { - return true; - } + while (generic != cur && toCheck != objectTypeInfo) { + cur = toCheck.IsGenericType ? ToTypeInfo(toCheck.GetGenericTypeDefinition()) : toCheck; toCheck = ToTypeInfo(toCheck.BaseType); } - return false; + return generic == cur; } private static Type GetTypeFromMapping(NullableDictionary typeMapping, JToken discriminatorToken, JsonSerializer serializer)