Skip to content

Commit

Permalink
AdditionalProperties are only added on the base class (#1451)
Browse files Browse the repository at this point in the history
* AdditionalProperties are only added on the base class

* Use base class

* add comment

Co-authored-by: Jochen Jonckheere <jochen.jonckheere@actemium.com>
Co-authored-by: Rico Suter <mail@rsuter.com>
  • Loading branch information
3 people authored Dec 14, 2021
1 parent b03746d commit 65dec69
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using NJsonSchema.CodeGeneration.CSharp;
using NJsonSchema.Generation;
Expand Down Expand Up @@ -43,6 +44,104 @@ public async Task When_additionalProperties_schema_is_set_for_object_then_specia
Assert.Contains("public System.Collections.Generic.IDictionary<string, object> 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<string, object> 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
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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" };
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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" };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,15 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings,
/// <summary>Gets a value indicating whether the C#8 nullable reference types are enabled for this file.</summary>
public bool GenerateNullableReferenceTypes => _settings.GenerateNullableReferenceTypes;

/// <summary>Gets a value indicating whether an additional properties type is available.</summary>
/// <summary>Gets a value indicating whether an additional properties type is available and needed.</summary>
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

/// <summary>Gets the type of the additional properties.</summary>
public string AdditionalPropertiesType => HasAdditionalPropertiesType ? "object" : null; // TODO: Find a way to use typed dictionaries
Expand Down

0 comments on commit 65dec69

Please sign in to comment.