From 809e4b24e7afd751854a1c5581c17db9872de2f8 Mon Sep 17 00:00:00 2001 From: Jochen Jonckheere Date: Tue, 30 Nov 2021 16:57:39 +0100 Subject: [PATCH 1/3] AdditionalProperties are only added on the base class --- .../AdditionalPropertiesTests.cs | 99 +++++++++++++++++++ .../CSharpJsonSerializerGeneratorTests.cs | 6 +- .../GeneralGeneratorTests.cs | 4 +- .../Models/ClassTemplateModel.cs | 3 +- 4 files changed, 106 insertions(+), 6 deletions(-) diff --git a/src/NJsonSchema.CodeGeneration.CSharp.Tests/AdditionalPropertiesTests.cs b/src/NJsonSchema.CodeGeneration.CSharp.Tests/AdditionalPropertiesTests.cs index ec32c631b..6f5329547 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp.Tests/AdditionalPropertiesTests.cs +++ b/src/NJsonSchema.CodeGeneration.CSharp.Tests/AdditionalPropertiesTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Text.RegularExpressions; using System.Threading.Tasks; using NJsonSchema.CodeGeneration.CSharp; using NJsonSchema.Generation; @@ -43,6 +44,104 @@ public async Task When_additionalProperties_schema_is_set_for_object_then_specia Assert.Contains("public System.Collections.Generic.IDictionary AdditionalProperties", code); } + [Fact] + public async Task When_using_SystemTextJson_additionalProperties_schema_is_set_for_object_then_special_property_is_rendered() + { + //// Arrange + var json = + @"{ + ""properties"": { + ""Pet"": { + ""type"": ""object"", + ""properties"": { + ""id"": { + ""type"": ""integer"", + ""format"": ""int64"" + }, + ""category"": { + ""type"": ""string"" + } + }, + ""additionalProperties"": { + ""type"": ""string"" + } + } + } +}"; + var schema = await JsonSchema.FromJsonAsync(json); + + //// Act + var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings() + { + JsonLibrary = CSharpJsonLibrary.SystemTextJson + }); + var code = generator.GenerateFile("Person"); + + //// Assert + Assert.Contains("[System.Text.Json.Serialization.JsonExtensionData]", code); + Assert.Contains("public System.Collections.Generic.IDictionary AdditionalProperties", code); + } + + [Fact] + public async Task When_using_SystemTextJson_additionalProperties_schema_is_set_for_object_then_special_property_is_rendered_only_for_base_class() + { + var json = + @"{ + ""properties"": { + ""dog"": { + ""allOf"": [ + { + ""$ref"": ""#/components/Pet"" + }, + { + ""description"": ""Dog"" + } + ] + }, + ""cat"": { + ""allOf"": [ + { + ""$ref"": ""#/components/Pet"" + }, + { + ""description"": ""Cat"" + } + ] + } + }, + ""components"": { + ""Pet"": { + ""type"": ""object"", + ""description"": ""Pet"", + ""properties"": { + ""id"": { + ""type"": ""integer"", + ""format"": ""int64"" + }, + ""category"": { + ""type"": ""string"" + } + } + } + } +}"; + + var schema = await JsonSchema.FromJsonAsync(json); + + //// Act + var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings() + { + JsonLibrary = CSharpJsonLibrary.SystemTextJson + }); + var code = generator.GenerateFile("Person"); + + //// Assert + var matches = Regex.Matches(code, @"(\[System\.Text\.Json\.Serialization\.JsonExtensionData\])"); + + // There are two matches, the Person class and the Pet class + Assert.Equal(2, matches.Count); + } + public class Page { } diff --git a/src/NJsonSchema.CodeGeneration.CSharp.Tests/CSharpJsonSerializerGeneratorTests.cs b/src/NJsonSchema.CodeGeneration.CSharp.Tests/CSharpJsonSerializerGeneratorTests.cs index 1e7df06b9..41b204477 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp.Tests/CSharpJsonSerializerGeneratorTests.cs +++ b/src/NJsonSchema.CodeGeneration.CSharp.Tests/CSharpJsonSerializerGeneratorTests.cs @@ -6,7 +6,7 @@ namespace NJsonSchema.CodeGeneration.CSharp.Tests public class CSharpJsonSerializerGeneratorTests { [Fact] - public void When_using_SytemTextJson_GenerateJsonSerializerParameterCode_generates_correctly() + public void When_using_SystemTextJson_GenerateJsonSerializerParameterCode_generates_correctly() { //// Arrange var additionalJsonConverters = new string[] { "AdditionalConverter1", "AdditionalConverter2" }; @@ -43,7 +43,7 @@ public void When_using_NewtonsoftJson_with_JsonConverters_GenerateJsonSerializer } [Fact] - public void When_using_SytemTextJson_with_JsonSerializerSettingsOrOptionsTransformationMethod_GenerateJsonSerializerParameterCode_generates_correctly() + public void When_using_SystemTextJson_with_JsonSerializerSettingsOrOptionsTransformationMethod_GenerateJsonSerializerParameterCode_generates_correctly() { //// Arrange var settings = new CSharpGeneratorSettings @@ -82,7 +82,7 @@ public void When_using_NewtonsoftJson_with_HandleReferences_and_JsonConverters_a } [Fact] - public void When_using_SytemTextJson_with_JsonConverters_GenerateJsonConvertersArrayCode_generates_correctly() + public void When_using_SystemTextJson_with_JsonConverters_GenerateJsonConvertersArrayCode_generates_correctly() { //// Arrange var additionalJsonConverters = new string[] { "AdditionalConverter1", "AdditionalConverter2" }; diff --git a/src/NJsonSchema.CodeGeneration.CSharp.Tests/GeneralGeneratorTests.cs b/src/NJsonSchema.CodeGeneration.CSharp.Tests/GeneralGeneratorTests.cs index 53b6ffabf..c7b766ea7 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp.Tests/GeneralGeneratorTests.cs +++ b/src/NJsonSchema.CodeGeneration.CSharp.Tests/GeneralGeneratorTests.cs @@ -1795,7 +1795,7 @@ private static void AssertCompile(string code) } [Fact] - public async Task When_using_SytemTextJson_without_JsonConverters_generates_FromJson_and_ToJson_correctly() + public async Task When_using_SystemTextJson_without_JsonConverters_generates_FromJson_and_ToJson_correctly() { //// Arrange var expectedToJsonMethod = @@ -1835,7 +1835,7 @@ public static Person FromJson(string data) } [Fact] - public async Task When_using_SytemTextJson_with_JsonConverters_generates_FromJson_and_ToJson_correctly() + public async Task When_using_SystemTextJson_with_JsonConverters_generates_FromJson_and_ToJson_correctly() { //// Arrange var expectedToJsonMethod = diff --git a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs index af1e29cc4..4e0632c83 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs +++ b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs @@ -69,7 +69,8 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings, !_schema.IsArray && !_schema.ActualTypeSchema.IsArray && (_schema.ActualTypeSchema.AllowAdditionalProperties || - _schema.ActualTypeSchema.AdditionalPropertiesSchema != null); + _schema.ActualTypeSchema.AdditionalPropertiesSchema != null) + && _schema.InheritedTypeSchema == null; /// Gets the type of the additional properties. public string AdditionalPropertiesType => HasAdditionalPropertiesType ? "object" : null; // TODO: Find a way to use typed dictionaries From 2d51472b07fb5f4e5014ce14c80115d5cc77db80 Mon Sep 17 00:00:00 2001 From: Rico Suter Date: Tue, 14 Dec 2021 20:57:48 +0100 Subject: [PATCH 2/3] Use base class --- .../Models/ClassTemplateModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs index 4e0632c83..d1023df03 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs +++ b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs @@ -62,7 +62,7 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings, /// Gets a value indicating whether the C#8 nullable reference types are enabled for this file. public bool GenerateNullableReferenceTypes => _settings.GenerateNullableReferenceTypes; - /// Gets a value indicating whether an additional properties type is available. + /// Gets a value indicating whether an additional properties type is available and needed. public bool HasAdditionalPropertiesType => !_schema.IsDictionary && !_schema.ActualTypeSchema.IsDictionary && @@ -70,7 +70,7 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings, !_schema.ActualTypeSchema.IsArray && (_schema.ActualTypeSchema.AllowAdditionalProperties || _schema.ActualTypeSchema.AdditionalPropertiesSchema != null) - && _schema.InheritedTypeSchema == null; + && BaseClass?.HasAdditionalPropertiesType != true; /// Gets the type of the additional properties. public string AdditionalPropertiesType => HasAdditionalPropertiesType ? "object" : null; // TODO: Find a way to use typed dictionaries From aca2f9c5f0fa5772b534ccc48f2c6c7857d99a33 Mon Sep 17 00:00:00 2001 From: Rico Suter Date: Tue, 14 Dec 2021 21:08:41 +0100 Subject: [PATCH 3/3] add comment --- .../Models/ClassTemplateModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs index d1023df03..4847682ae 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs +++ b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs @@ -70,7 +70,7 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings, !_schema.ActualTypeSchema.IsArray && (_schema.ActualTypeSchema.AllowAdditionalProperties || _schema.ActualTypeSchema.AdditionalPropertiesSchema != null) - && BaseClass?.HasAdditionalPropertiesType != true; + && BaseClass?.HasAdditionalPropertiesType != true; // if base class already has extension data array, we need to avoid it in the subclass /// Gets the type of the additional properties. public string AdditionalPropertiesType => HasAdditionalPropertiesType ? "object" : null; // TODO: Find a way to use typed dictionaries