NJsonSchema icon indicating copy to clipboard operation
NJsonSchema copied to clipboard

Code produced by CSharpGenerator for enums does not work with System.Text.Json

Open virovets64 opened this issue 3 years ago • 2 comments

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

  1. System.Runtime.Serialization.EnumMember attribute is ignored by System.Text.Json, see https://github.com/dotnet/runtime/issues/31081
  2. System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter)) attribute generated for StarType property overloads my JsonStringEnumConverter specified in JsonSerializerOptions.

I tried to find a workaround but failed.

Best regards, Mikhail Virovets

virovets64 avatar Jun 09 '21 08:06 virovets64

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 -%}

eholman avatar Sep 22 '21 11:09 eholman

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.

jochenjonc avatar Nov 26 '21 15:11 jochenjonc