Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for STJ-native C# code gen #1675

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -80,5 +80,27 @@ public async Task When_schema_has_base_schema_then_it_is_referenced_with_STJ()
Assert.Contains("[JsonInheritanceAttribute(\"Banana\", typeof(Banana))]", code);
Assert.Contains("public class JsonInheritanceConverter<TBase> : System.Text.Json.Serialization.JsonConverter<TBase>", code);
}

[Fact]
public async Task When_using_STJ_polymorphic_serialization_then_NSwag_inheritance_converter_and_attributes_are_not_generated()
{
//// Arrange
var json = JsonSchema.FromType<MyContainer>();
var data = json.ToJson();

var generator = new CSharpGenerator(json, new CSharpGeneratorSettings
{
JsonLibrary = CSharpJsonLibrary.SystemTextJson,
JsonPolymorphicSerializationStyle = CSharpJsonPolymorphicSerializationStyle.SystemTextJson
});

//// Act
var code = generator.GenerateFile();

//// Assert
Assert.DoesNotContain("[JsonInheritanceConverter", code);
Assert.DoesNotContain("[JsonInheritanceAttribute", code);
Assert.DoesNotContain("public class JsonInheritanceConverter", code);
}
}
}
27 changes: 27 additions & 0 deletions src/NJsonSchema.CodeGeneration.CSharp.Tests/InheritanceTests.cs
Expand Up @@ -156,6 +156,33 @@ public async Task When_definitions_inherit_from_root_schema()
Assert.Contains("[JsonInheritanceAttribute(\"PersianCat\", typeof(PersianCat))]", code);
}

[Fact]
public async Task When_definitions_inherit_from_root_schema_and_STJ_polymorphism()
{
//// Arrange
var path = GetTestDirectory() + "/References/Animal.json";

//// Act
var schema = await JsonSchema.FromFileAsync(path);
var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings
{
ClassStyle = CSharpClassStyle.Record,
JsonLibrary = CSharpJsonLibrary.SystemTextJson,
JsonPolymorphicSerializationStyle = CSharpJsonPolymorphicSerializationStyle.SystemTextJson
});

//// Act
var code = generator.GenerateFile();

//// Assert
Assert.Contains("public abstract partial class Animal", code);
Assert.Contains("public partial class Cat : Animal", code);
Assert.Contains("public partial class PersianCat : Cat", code);
Assert.Contains("[System.Text.Json.Serialization.JsonPolymorphic(TypeDiscriminatorPropertyName = \"discriminator\")]", code);
Assert.Contains("[System.Text.Json.Serialization.JsonDerivedType(typeof(Cat), typeDiscriminator: \"Cat\")]", code);
Assert.Contains("[System.Text.Json.Serialization.JsonDerivedType(typeof(PersianCat), typeDiscriminator: \"PersianCat\")]", code);
}

private string GetTestDirectory()
{
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
Expand Down
Expand Up @@ -39,6 +39,7 @@ public CSharpGeneratorSettings()

ClassStyle = CSharpClassStyle.Poco;
JsonLibrary = CSharpJsonLibrary.NewtonsoftJson;
JsonPolymorphicSerializationStyle = CSharpJsonPolymorphicSerializationStyle.NSwag;

RequiredPropertiesMustBeDefined = true;
GenerateDataAnnotations = true;
Expand Down Expand Up @@ -120,6 +121,9 @@ public CSharpGeneratorSettings()
/// <summary>Gets or sets the CSharp JSON library to use (default: 'NewtonsoftJson', 'SystemTextJson' is experimental/not complete).</summary>
public CSharpJsonLibrary JsonLibrary { get; set; }

/// <summary>Gets or sets the CSharp JSON polymorphic serialization style (default: 'NSwag', 'SystemTextJson' is experimental/not complete).</summary>
public CSharpJsonPolymorphicSerializationStyle JsonPolymorphicSerializationStyle { get; set; }

/// <summary>Gets or sets the access modifier of generated classes and interfaces (default: 'public').</summary>
public string TypeAccessModifier { get; set; }

Expand Down
@@ -0,0 +1,12 @@
namespace NJsonSchema.CodeGeneration.CSharp
{
/// <summary>The CSharp JSON polymorphic serialization style.</summary>
public enum CSharpJsonPolymorphicSerializationStyle
{
/// <summary>Use NSwag polymorphic serialization</summary>
NSwag,

/// <summary>Use System.Text.Json polymorphic serialization</summary>
SystemTextJson
}
}
Expand Up @@ -53,6 +53,9 @@ public class ClassTemplateModel : ClassTemplateModelBase
/// <summary>Gets a value indicating whether to use System.Text.Json</summary>
public bool UseSystemTextJson => _settings.JsonLibrary == CSharpJsonLibrary.SystemTextJson;

/// <summary>Gets a value indicating whether to use System.Text.Json polymorphic serialization</summary>
public bool UseSystemTextJsonPolymorphicSerialization => _settings.JsonPolymorphicSerializationStyle == CSharpJsonPolymorphicSerializationStyle.SystemTextJson;

/// <summary>Gets or sets the class name.</summary>
public override string ClassName { get; }

Expand Down
Expand Up @@ -21,5 +21,8 @@ public JsonInheritanceConverterTemplateModel(CSharpGeneratorSettings settings)

/// <summary>Gets a value indicating whether to use System.Text.Json</summary>
public bool UseSystemTextJson => _settings.JsonLibrary == CSharpJsonLibrary.SystemTextJson;

/// <summary>Gets a value indicating whether to use System.Text.Json polymorphic serialization</summary>
public bool UseSystemTextJsonPolymorphicSerialization => _settings.JsonPolymorphicSerializationStyle == CSharpJsonPolymorphicSerializationStyle.SystemTextJson;
}
}
8 changes: 8 additions & 0 deletions src/NJsonSchema.CodeGeneration.CSharp/Templates/Class.liquid
Expand Up @@ -5,14 +5,22 @@
{%- endif -%}
{%- if HasDiscriminator -%}
{%- if UseSystemTextJson -%}
{%- if UseSystemTextJsonPolymorphicSerialization -%}
[System.Text.Json.Serialization.JsonPolymorphic(TypeDiscriminatorPropertyName = "{{ Discriminator }}")]
{%- else -%}
[JsonInheritanceConverter(typeof({{ ClassName }}), "{{ Discriminator }}")]
{%- endif -%}
{%- else -%}
[Newtonsoft.Json.JsonConverter(typeof(JsonInheritanceConverter), "{{ Discriminator }}")]
{%- endif -%}
{%- for derivedClass in DerivedClasses -%}
{%- if derivedClass.IsAbstract != true -%}
{%- if UseSystemTextJson and UseSystemTextJsonPolymorphicSerialization -%}
[System.Text.Json.Serialization.JsonDerivedType(typeof({{ derivedClass.ClassName }}), typeDiscriminator: "{{ derivedClass.Discriminator }}")]
{%- else -%}
[JsonInheritanceAttribute("{{ derivedClass.Discriminator }}", typeof({{ derivedClass.ClassName }}))]
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "{{ ToolchainVersion }}")]
Expand Down
@@ -1,4 +1,5 @@
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "{{ ToolchainVersion }}")]
{%- if UseSystemTextJsonPolymorphicSerialization == false -%}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "{{ ToolchainVersion }}")]
[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Interface, AllowMultiple = true)]
internal class JsonInheritanceAttribute : System.Attribute
{
Expand All @@ -11,4 +12,5 @@ internal class JsonInheritanceAttribute : System.Attribute
public string Key { get; }

public System.Type Type { get; }
}
}
{%- endif -%}
@@ -1,4 +1,5 @@
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "{{ ToolchainVersion }}")]
{%- if UseSystemTextJsonPolymorphicSerialization == false -%}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "{{ ToolchainVersion }}")]
{%- if UseSystemTextJson -%}
internal class JsonInheritanceConverterAttribute : System.Text.Json.Serialization.JsonConverterAttribute
{
Expand Down Expand Up @@ -236,3 +237,4 @@ public class JsonInheritanceConverter : Newtonsoft.Json.JsonConverter
}
}
{%- endif -%}
{%- endif -%}