Skip to content

Commit

Permalink
Tolerate schema properties named AdditionalProperties
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma committed Nov 21, 2023
1 parent 63ee615 commit b808644
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NJsonSchema.Annotations;
using NJsonSchema.Generation;
using NJsonSchema.NewtonsoftJson.Generation;
using Xunit;

Expand Down Expand Up @@ -1890,6 +1889,35 @@ public async Task When_schema_has_AdditionProperties_schema_then_JsonExtensionDa

//// Assert
Assert.Contains("JsonExtensionData", output);
Assert.Contains("IDictionary<string, object> AdditionalProperties\n", output);
}


public class ClassWithAdditionalProperties
{
public string AdditionalProperties { get; set; }

[JsonExtensionData]
public IDictionary<string, object> ExtensionData { get; set; }
}

[Fact]
public async Task When_schema_has_AdditionProperties_schema_and_type_has_member_with_same_name()
{
//// Arrange
var schema = NewtonsoftJsonSchemaGenerator.FromType<ClassWithAdditionalProperties>(new NewtonsoftJsonSchemaGeneratorSettings { SchemaType = SchemaType.OpenApi3 });
var json = schema.ToJson();

var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings
{
ClassStyle = CSharpClassStyle.Poco
});

//// Act
var output = generator.GenerateFile("PersonAddress");

//// Assert
Assert.Contains("IDictionary<string, object> AdditionalProperties2\n", output);
}

[Fact]
Expand Down
12 changes: 5 additions & 7 deletions src/NJsonSchema.CodeGeneration.CSharp/CSharpGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Collections.Generic;
using System.Linq;
using NJsonSchema.CodeGeneration.CSharp.Models;
using NJsonSchema.CodeGeneration.Models;

namespace NJsonSchema.CodeGeneration.CSharp
{
Expand Down Expand Up @@ -116,17 +115,16 @@ private CodeArtifact GenerateClass(JsonSchema schema, string typeName)
{
var model = new ClassTemplateModel(typeName, Settings, _resolver, schema, RootObject);

RenamePropertyWithSameNameAsClass(typeName, model.Properties);
RenamePropertyWithSameNameAsClass(typeName, model._properties);

var template = Settings.TemplateFactory.CreateTemplate("CSharp", "Class", model);
return new CodeArtifact(typeName, model.BaseClassName, CodeArtifactType.Class, CodeArtifactLanguage.CSharp, CodeArtifactCategory.Contract, template);
}

private static void RenamePropertyWithSameNameAsClass(string typeName, IEnumerable<PropertyModel> properties)
private static void RenamePropertyWithSameNameAsClass(string typeName, List<PropertyModel> properties)
{
var propertyModels = properties as PropertyModel[] ?? properties.ToArray();
PropertyModel? propertyWithSameNameAsClass = null;
foreach (var p in propertyModels)
foreach (var p in properties)
{
if (p.PropertyName == typeName)
{
Expand All @@ -139,12 +137,12 @@ private static void RenamePropertyWithSameNameAsClass(string typeName, IEnumerab
{
var number = 1;
var candidate = typeName + number;
while (propertyModels.Any(p => p.PropertyName == candidate))
while (properties.Exists(p => p.PropertyName == candidate))
{
number++;
}

propertyWithSameNameAsClass.PropertyName = propertyWithSameNameAsClass.PropertyName + number;
propertyWithSameNameAsClass.PropertyName += number;
}
}

Expand Down
34 changes: 26 additions & 8 deletions src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class ClassTemplateModel : ClassTemplateModelBase
private readonly CSharpTypeResolver _resolver;
private readonly JsonSchema _schema;
private readonly CSharpGeneratorSettings _settings;
internal readonly List<PropertyModel> _properties;
private readonly List<PropertyModel> _allProperties;

/// <summary>Initializes a new instance of the <see cref="ClassTemplateModel"/> class.</summary>
/// <param name="typeName">Name of the type.</param>
Expand All @@ -34,19 +36,32 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings,
_settings = settings;

ClassName = typeName;
Properties = _schema.ActualProperties.Values
.Where(p => !p.IsInheritanceDiscriminator)
.Select(property => new PropertyModel(this, property, _resolver, _settings))
.ToArray();

AdditionalPropertiesPropertyName = "AdditionalProperties";
var actualProperties = _schema.ActualProperties;
_properties = new List<PropertyModel>(actualProperties.Count);
foreach (var property in actualProperties.Values)
{
if (!property.IsInheritanceDiscriminator)
{
_properties.Add(new PropertyModel(this, property, _resolver, _settings));
if (property.Name == AdditionalPropertiesPropertyName)
{
AdditionalPropertiesPropertyName += "2";
}
}
}

if (schema.InheritedSchema != null)
{
BaseClass = new ClassTemplateModel(BaseClassName!, settings, resolver, schema.InheritedSchema, rootObject);
AllProperties = Properties.Concat(BaseClass.AllProperties).ToArray();
_allProperties = new List<PropertyModel>(_properties.Count + BaseClass._allProperties.Count);
_allProperties.AddRange(_properties);
_allProperties.AddRange(BaseClass._allProperties);
}
else
{
AllProperties = Properties;
_allProperties = _properties;
}
}

Expand Down Expand Up @@ -85,11 +100,14 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings,
// _schema.AdditionalPropertiesSchema.IsNullable(_settings.SchemaType),
// string.Empty) : null;

/// <summary>Gets property name for the additional properties.</summary>
public string? AdditionalPropertiesPropertyName { get; private set; }

/// <summary>Gets the property models.</summary>
public IEnumerable<PropertyModel> Properties { get; }
public IEnumerable<PropertyModel> Properties => _properties;

/// <summary>Gets the property models with inherited properties.</summary>
public IEnumerable<PropertyModel> AllProperties { get; }
public IEnumerable<PropertyModel> AllProperties => _allProperties;

/// <summary>Gets a value indicating whether the class has description.</summary>
public bool HasDescription => !(_schema is JsonSchemaProperty) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
{%- else -%}
[Newtonsoft.Json.JsonExtensionData]
{%- endif -%}
public System.Collections.Generic.IDictionary<string, {{ AdditionalPropertiesType }}> AdditionalProperties
public System.Collections.Generic.IDictionary<string, {{ AdditionalPropertiesType }}> {{ AdditionalPropertiesPropertyName }}
{
get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary<string, {{ AdditionalPropertiesType }}>()); }
{{PropertySetterAccessModifier}}set { _additionalProperties = value; }
Expand Down

0 comments on commit b808644

Please sign in to comment.