diff --git a/src/NJsonSchema.Tests/Generation/KnownTypeGenerationTests.cs b/src/NJsonSchema.Tests/Generation/KnownTypeGenerationTests.cs index 070be991d..3bf6ea050 100644 --- a/src/NJsonSchema.Tests/Generation/KnownTypeGenerationTests.cs +++ b/src/NJsonSchema.Tests/Generation/KnownTypeGenerationTests.cs @@ -20,9 +20,27 @@ public class Person { } + public class Pen + { + } + + public class Pencil + { + } + + [KnownType("GetKnownTypes")] + public class WritingInstrument + { + public static Type[] GetKnownTypes() + { + return new[] { typeof(Pen), typeof(Pencil) }; + } + } + public class Container { public Person Person { get; set; } + public WritingInstrument WritingInstrument { get; set; } } [TestMethod] @@ -37,5 +55,23 @@ public async Task When_KnownType_attribute_exists_then_specified_classes_are_als //// Assert Assert.IsTrue(schema.Definitions.Any(s => s.Key == "Teacher")); } + + public async Task ReproAsync() + { + var schema = await JsonSchema4.FromTypeAsync(); + } + [TestMethod] + public async Task When_KnownType_attribute_includes_method_name_then_specified_classes_are_also_generated() + { + //// Arrange + + //// Act + var schema = await JsonSchema4.FromTypeAsync(); + var schemaData = schema.ToJson(); + + //// Assert + Assert.IsTrue(schema.Definitions.Any(s => s.Key == "Pen")); + Assert.IsTrue(schema.Definitions.Any(s => s.Key == "Pencil")); + } } } diff --git a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs index 84acd455d..25c3c3c76 100644 --- a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs +++ b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs @@ -298,11 +298,32 @@ private async Task GenerateKnownTypesAsync(Type type, JsonSchemaResolver schemaR { foreach (dynamic knownTypeAttribute in type.GetTypeInfo().GetCustomAttributes().Where(a => a.GetType().Name == "KnownTypeAttribute")) { - var typeDescription = JsonObjectTypeDescription.FromType(knownTypeAttribute.Type, null, Settings.DefaultEnumHandling); - var isIntegerEnum = typeDescription.Type == JsonObjectType.Integer; + if (knownTypeAttribute.Type != null) + { + var typeDescription = JsonObjectTypeDescription.FromType(knownTypeAttribute.Type, null, Settings.DefaultEnumHandling); + var isIntegerEnum = typeDescription.Type == JsonObjectType.Integer; + + if (!schemaResolver.HasSchema(knownTypeAttribute.Type, isIntegerEnum)) + await GenerateAsync(knownTypeAttribute.Type, schemaResolver).ConfigureAwait(false); + } + else if (!string.IsNullOrWhiteSpace(knownTypeAttribute.MethodName)) + { + var methodInfo = type.GetRuntimeMethod((string)knownTypeAttribute.MethodName, new Type[0]); + var knownTypes = methodInfo.Invoke(null, null) as Type[]; + + foreach (var knownType in knownTypes) + { + var typeDescription = JsonObjectTypeDescription.FromType(knownType, null, Settings.DefaultEnumHandling); + var isIntegerEnum = typeDescription.Type == JsonObjectType.Integer; - if (!schemaResolver.HasSchema(knownTypeAttribute.Type, isIntegerEnum)) - await GenerateAsync(knownTypeAttribute.Type, schemaResolver).ConfigureAwait(false); + if (!schemaResolver.HasSchema(knownType, isIntegerEnum)) + await GenerateAsync(knownType, schemaResolver).ConfigureAwait(false); + } + } + else + { + throw new ArgumentException($"A KnownType attribute on {type.FullName} does not specify a type or a method name.", nameof(type)); + } } }