RicoSuter/NJsonSchema

Generated JSON deserializer fails at runtime when schema enum contains duplicate keys

Open

#800 opened on Oct 28, 2018

View on GitHub
 (2 comments) (0 reactions) (0 assignees)C# (550 forks)github user discovery
help wantedtype: bug

Repository metrics

Stars
 (1,578 stars)
PR merge metrics
 (Avg merge 39d 6h) (1 merged PR in 30d)

Description

The following is the definition of the System.Net.HttpStatusCode type (shortened) from .nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll:

namespace System.Net
{
    //
    // Summary:
    //     Contains the values of status codes defined for HTTP.
    public enum HttpStatusCode
    {
        //
        // Summary:
        //     Equivalent to HTTP status 300. System.Net.HttpStatusCode.Ambiguous indicates
        //     that the requested information has multiple representations. The default action
        //     is to treat this status as a redirect and follow the contents of the Location
        //     header associated with this response.
        Ambiguous = 300,
        //
        // Summary:
        //     Equivalent to HTTP status 300. System.Net.HttpStatusCode.MultipleChoices indicates
        //     that the requested information has multiple representations. The default action
        //     is to treat this status as a redirect and follow the contents of the Location
        //     header associated with this response.
        MultipleChoices = 300,
    }
}

Per this StackOverflow question (which references the C# spec), this is allowed and correct syntax.

Generating the schema

var jsonSchema = (await NJsonSchema.JsonSchema4.FromTypeAsync(typeof(System.Net.HttpStatusCode))).ToJson();

Produces this (shortened) JSON schema:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "HttpStatusCode",
  "type": "integer",
  "description": "",
  "x-enumNames": [
    "MultipleChoices",
    "Ambiguous"
  ],
  "enum": [
    300,
    300
  ]
}

After a bit more processing (I'm using a model containing a HttpStatusCode property in a Web API, which gets then converted via NSwag to a Swagger definition, which then again is used to create a C# client) this is the generated C# client code (shortened):

[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.11.0.0 (Newtonsoft.Json v9.0.0.0)")]
    public enum HttpStatusCode
    {   
        [System.Runtime.Serialization.EnumMember(Value = "Ambiguous")]
        MultipleChoices = 14,
    
        [System.Runtime.Serialization.EnumMember(Value = "Ambiguous")]
        Ambiguous = 15
    }

This just fails at runtime when deserializing with Newtonsoft.Json:

System.InvalidOperationException : Enum name 'Ambiguous' already exists on enum 'HttpStatusCode'.

The workaround for me is to simply use the System.Net.HttpStatusCode enum in my generated client instead of the generated one.

Contributor guide