NJsonSchema
NJsonSchema copied to clipboard
Code produced by CSharpGenerator for enums does not work with System.Text.Json
Hello! I'm trying to use CSharpGenerator to generate C# code from JSON schema. The schema contains enums with camelStyle members. But when I serialize the generated classes with System.Text.Json, the resulting JSON contains PascalStyle enums, which violates the schema.
To reproduce
Schema example:
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"starType": {
"type": "string",
"enum": [ "redGiant", "whiteDwarf" ]
}
}
}
I run the generator in the following way:
string code = new CSharpGenerator(schema, new CSharpGeneratorSettings
{
JsonLibrary = CSharpJsonLibrary.SystemTextJson,
Namespace = "Example"
}).GenerateFile("Star");
Here is the code generated:
//----------------------
// <auto-generated>
// Generated using the NJsonSchema v10.4.4.0 (Newtonsoft.Json v9.0.0.0) (http://NJsonSchema.org)
// </auto-generated>
//----------------------
namespace Example
{
#pragma warning disable // Disable all warnings
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.4.0 (Newtonsoft.Json v9.0.0.0)")]
public partial class Star
{
[System.Text.Json.Serialization.JsonPropertyName("starType")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
public StarType StarType { get; set; }
private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();
[System.Text.Json.Serialization.JsonExtensionData]
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
{
get { return _additionalProperties; }
set { _additionalProperties = value; }
}
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.4.0 (Newtonsoft.Json v9.0.0.0)")]
public enum StarType
{
[System.Runtime.Serialization.EnumMember(Value = @"redGiant")]
RedGiant = 0,
[System.Runtime.Serialization.EnumMember(Value = @"whiteDwarf")]
WhiteDwarf = 1,
}
}
Then I serialize the generated class:
static void Main(string[] args)
{
var star = new Example.Star()
{
StarType = Example.StarType.RedGiant
};
string serialized = JsonSerializer.Serialize(star);
Console.WriteLine(serialized);
}
The resulting JSON is
{
"starType": "RedGiant"
}
Adding JsonStringEnumConverter has no effect:
string serialized = JsonSerializer.Serialize(star, new JsonSerializerOptions
{
Converters =
{
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
}
});
Suggestions
-
System.Runtime.Serialization.EnumMember
attribute is ignored by System.Text.Json, see https://github.com/dotnet/runtime/issues/31081 -
System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))
attribute generated forStarType
property overloads myJsonStringEnumConverter
specified inJsonSerializerOptions
.
I tried to find a workaround but failed.
Best regards, Mikhail Virovets
I'm having the exact issue where the EnumMemberAttribute value is not read. I also have a custom converter available, added to the JsonSerializerOptions
of the generated client.
Currently I'm digging through the code of NJsonSchema. At this moment I think it should become optional to get the converter attribues generated in C#, regardless jsonLibrary
setting - at this moment the option is not there.
{% if property.IsStringEnum -%}
{% if UseSystemTextJson -%}
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
{% else -%}
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
{% endif -%}
{% endif -%}
I agree with @eholman, it should be optional to have the JsonConverter attribute added or not. And if possible to use the JsonStringEnumMemberConvertor from the Macross.Json.Extensions or other custom one.