RicoSuter/NJsonSchema

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

Aperta

#800 aperta il 28 ott 2018

 (2 commenti) (0 reazioni) (0 assegnatari)C# (549 fork)github user discovery
help wantedtype: bug

Metriche repository

Star
 (1581 stelle)
Metriche merge PR
 (Merge medio 39g 6h) (1 PR mergiata in 30 g)

Descrizione

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.

Guida contributor