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 cff1db46e..d1f938522 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp.Tests/GeneralGeneratorTests.cs +++ b/src/NJsonSchema.CodeGeneration.CSharp.Tests/GeneralGeneratorTests.cs @@ -1830,7 +1830,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 = @@ -1870,7 +1870,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..4847682ae 100644 --- a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs +++ b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs @@ -62,14 +62,15 @@ 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 && !_schema.IsArray && !_schema.ActualTypeSchema.IsArray && (_schema.ActualTypeSchema.AllowAdditionalProperties || - _schema.ActualTypeSchema.AdditionalPropertiesSchema != null); + _schema.ActualTypeSchema.AdditionalPropertiesSchema != null) + && 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