From c7d045c79caa224d3b13f0c993772c1ccc79583a Mon Sep 17 00:00:00 2001 From: alb3ric Date: Fri, 7 Dec 2018 15:48:02 +0100 Subject: [PATCH 1/4] Support oneOf inheritance for JsonSchema Generation --- .../Generation/JsonSchemaGenerator.cs | 63 ++++++++++++------- src/NJsonSchema/JsonSchema4.cs | 4 ++ 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs index 92e228e1d..514a63b32 100644 --- a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs +++ b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs @@ -274,23 +274,37 @@ public virtual async Task GenerateWithReferenceAndNullabilityAsync< var useDirectReference = Settings.AllowReferencesWithProperties || !JsonConvert.DeserializeObject(JsonConvert.SerializeObject(referencingSchema)).Properties().Any(); // TODO: Improve performance - if (useDirectReference && referencingSchema.OneOf.Count == 0) + //TODO : use InheritanceMode ? + if (Settings.SchemaType == SchemaType.JsonSchema && referencedSchema.KnownTypesSchemas.Any()) { - referencingSchema.Reference = referencedSchema.ActualSchema; - } - else if (Settings.SchemaType != SchemaType.Swagger2) - { - referencingSchema.OneOf.Add(new JsonSchema4 + foreach (var schema in referencedSchema.KnownTypesSchemas) { - Reference = referencedSchema.ActualSchema - }); + referencingSchema.OneOf.Add(new JsonSchema4 + { + Reference = schema + }); + } } else { - referencingSchema.AllOf.Add(new JsonSchema4 + if (useDirectReference && referencingSchema.OneOf.Count == 0) { - Reference = referencedSchema.ActualSchema - }); + referencingSchema.Reference = referencedSchema.ActualSchema; + } + else if (Settings.SchemaType != SchemaType.Swagger2) + { + referencingSchema.OneOf.Add(new JsonSchema4 + { + Reference = referencedSchema.ActualSchema + }); + } + else + { + referencingSchema.AllOf.Add(new JsonSchema4 + { + Reference = referencedSchema.ActualSchema + }); + } } return referencingSchema; @@ -350,7 +364,7 @@ protected virtual async Task GenerateObjectAsync(Type type, GenerateInheritanceDiscriminator(type, rootSchema, schema); - await GenerateKnownTypesAsync(type, schemaResolver).ConfigureAwait(false); + schema.KnownTypesSchemas = new System.Collections.ObjectModel.ReadOnlyCollection(await GenerateKnownTypesAsync(type, schemaResolver).ConfigureAwait(false)); if (Settings.GenerateXmlObjects) schema.GenerateXmlObjectForType(type); @@ -645,8 +659,10 @@ protected virtual string[] GetTypeProperties(Type type) return null; } - private async Task GenerateKnownTypesAsync(Type type, JsonSchemaResolver schemaResolver) + private async Task> GenerateKnownTypesAsync(Type type, JsonSchemaResolver schemaResolver) { + var knownTypeSchemas = new List(); + var attributes = type.GetTypeInfo() .GetCustomAttributes(Settings.GetActualFlattenInheritanceHierarchy(type)); @@ -660,17 +676,16 @@ private async Task GenerateKnownTypesAsync(Type type, JsonSchemaResolver schemaR foreach (dynamic attribute in knownTypeAttributes) { if (attribute.Type != null) - await AddKnownTypeAsync(attribute.Type, schemaResolver).ConfigureAwait(false); + knownTypeSchemas.Add(await AddKnownTypeAsync(attribute.Type, schemaResolver)); else if (attribute.MethodName != null) { var methodInfo = type.GetRuntimeMethod((string)attribute.MethodName, new Type[0]); if (methodInfo != null) { var knownTypes = methodInfo.Invoke(null, null) as IEnumerable; - if (knownTypes != null) + foreach (var knownType in knownTypes) { - foreach (var knownType in knownTypes) - await AddKnownTypeAsync(knownType, schemaResolver).ConfigureAwait(false); + knownTypeSchemas.Add(await AddKnownTypeAsync(knownType, schemaResolver)); } } } @@ -680,25 +695,29 @@ private async Task GenerateKnownTypesAsync(Type type, JsonSchemaResolver schemaR } foreach (var jsonConverterAttribute in attributes - .Where(a => a.GetType().IsAssignableTo("JsonInheritanceAttribute", TypeNameStyle.Name))) + .Where(a => a.GetType().IsAssignableTo("JsonInheritanceAttribute", TypeNameStyle.Name))) { var knownType = ReflectionExtensions.TryGetPropertyValue( jsonConverterAttribute, "Type", null); if (knownType != null) { - await AddKnownTypeAsync(knownType, schemaResolver).ConfigureAwait(false); + knownTypeSchemas.Add(await AddKnownTypeAsync(type, schemaResolver)); } } + return knownTypeSchemas; } - private async Task AddKnownTypeAsync(Type type, JsonSchemaResolver schemaResolver) + + private async Task AddKnownTypeAsync(Type type, JsonSchemaResolver schemaResolver) { var typeDescription = Settings.ReflectionService.GetDescription(type, null, Settings); var isIntegerEnum = typeDescription.Type == JsonObjectType.Integer; - if (!schemaResolver.HasSchema(type, isIntegerEnum)) - await GenerateAsync(type, schemaResolver).ConfigureAwait(false); + if (schemaResolver.HasSchema(type, isIntegerEnum)) + return schemaResolver.GetSchema(type, isIntegerEnum); + else + return await GenerateAsync(type, schemaResolver).ConfigureAwait(false); } private async Task GenerateInheritanceAsync(Type type, JsonSchema4 schema, JsonSchemaResolver schemaResolver) diff --git a/src/NJsonSchema/JsonSchema4.cs b/src/NJsonSchema/JsonSchema4.cs index 57f266974..703b8542d 100644 --- a/src/NJsonSchema/JsonSchema4.cs +++ b/src/NJsonSchema/JsonSchema4.cs @@ -330,6 +330,10 @@ public IDictionary ActualProperties [JsonIgnore] public JsonSchema4 ParentSchema => Parent as JsonSchema4; + /// Gets or sets the KnownTypes Schemas + [JsonIgnore] + public ReadOnlyCollection KnownTypesSchemas { get; set; } + /// Gets the parent schema of this schema. [JsonIgnore] public virtual object Parent { get; set; } From d88d06f338f4942a0c3c0a047d4e01f9dfe2ff74 Mon Sep 17 00:00:00 2001 From: alb3ric Date: Fri, 7 Dec 2018 16:13:22 +0100 Subject: [PATCH 2/4] Support oneOf inheritance for JsonSchema Generation Fix GenerateKnownTypesAsync --- src/NJsonSchema/Generation/JsonSchemaGenerator.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs index 514a63b32..623309ca6 100644 --- a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs +++ b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs @@ -683,9 +683,10 @@ private async Task> GenerateKnownTypesAsync(Type type, JsonSc if (methodInfo != null) { var knownTypes = methodInfo.Invoke(null, null) as IEnumerable; - foreach (var knownType in knownTypes) + if (knownTypes != null) { - knownTypeSchemas.Add(await AddKnownTypeAsync(knownType, schemaResolver)); + foreach (var knownType in knownTypes) + knownTypeSchemas.Add(await AddKnownTypeAsync(knownType, schemaResolver)); } } } From cab6bf9c9b00b5b9ee360653072e03464bdb2bd0 Mon Sep 17 00:00:00 2001 From: alb3ric Date: Mon, 10 Dec 2018 17:05:48 +0100 Subject: [PATCH 3/4] Support oneOf inheritance for JsonSchema Generation Fix assiging oneOf --- src/NJsonSchema/Generation/JsonSchemaGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs index 623309ca6..5ee6c2012 100644 --- a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs +++ b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs @@ -275,9 +275,9 @@ public virtual async Task GenerateWithReferenceAndNullabilityAsync< !JsonConvert.DeserializeObject(JsonConvert.SerializeObject(referencingSchema)).Properties().Any(); // TODO: Improve performance //TODO : use InheritanceMode ? - if (Settings.SchemaType == SchemaType.JsonSchema && referencedSchema.KnownTypesSchemas.Any()) + if (Settings.SchemaType == SchemaType.JsonSchema && referencedSchema.ActualSchema.KnownTypesSchemas?.Any() == true) { - foreach (var schema in referencedSchema.KnownTypesSchemas) + foreach (var schema in referencedSchema.ActualSchema.KnownTypesSchemas) { referencingSchema.OneOf.Add(new JsonSchema4 { From e870190cbdeaf582f6ec0c64b2a44d8e21b91e8d Mon Sep 17 00:00:00 2001 From: alb3ric Date: Mon, 7 Jan 2019 15:38:17 +0100 Subject: [PATCH 4/4] Support oneOf inheritance for JsonSchema Generation --- src/NJsonSchema/Generation/JsonSchemaGenerator.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs index 5ee6c2012..efbbf6934 100644 --- a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs +++ b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs @@ -279,6 +279,7 @@ public virtual async Task GenerateWithReferenceAndNullabilityAsync< { foreach (var schema in referencedSchema.ActualSchema.KnownTypesSchemas) { + referencingSchema.Type = JsonObjectType.Object; referencingSchema.OneOf.Add(new JsonSchema4 { Reference = schema