1

The main question is that if the enum can or cannot have "." in the middle of the name, my example is the following:

So someone sent me this openapi yaml file, bellow, that i am generating a controller in c# for. This is the yaml I received:

  /actions/MyAction:
    post:
      summary: blahblah
      tags:
      - action
      parameters:
      - in: body
        name: MyAction
        required: true
        schema:
          type: object
          properties:
            data: 
              type: object
              properties:
                target:
                  type: string
                location:
                  description: thelocation
                  type: string
                  enum:
                    - location.Outdoor1
                    - location.Outdoor2
                    - location.Outdoor3

The object class generated in c# for :

 public partial class Data2
    {
        [Newtonsoft.Json.JsonProperty("target", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
        public stringTarget { get; set; }

        [Newtonsoft.Json.JsonProperty("location", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
[Newtonsoft.Json.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
public Data2Location? Location { get; set; }
    }

And for the enum i have:

public enum Data2Location
    {
        [System.Runtime.Serialization.EnumMember(Value = @"location.Outdoor1")]
        location_Outdoor1= 0,

        [System.Runtime.Serialization.EnumMember(Value = @"location.Outdoor2")]
        location_Outdoor2 = 1,

        [System.Runtime.Serialization.EnumMember(Value = @"location.Outdoor3")]
        location_Outdoor3= 2,
    }

the controller

[Microsoft.AspNetCore.Mvc.HttpPost, Microsoft.AspNetCore.Mvc.Route("actions/MyAction")]
        public Microsoft.AspNetCore.Mvc.IActionResult MyAction([Microsoft.AspNetCore.Mvc.FromBody] Data2data)
        {
            return _implementation.MyAction(data);
        }

My troubles are with the enum "thelocation" because when i send a request from Postman the all object comes null in the method above for the request: post to http://localhost:5000/api/v1/actions/Myaction With body:

{
    "data": {
        "target": "thetarget"
        "location":"location.Outdoor2"
    }
} 
mfabruno
  • 131
  • 3
  • 12
  • 1
    According to your definition, the field in the JSON body is supposed to be named `"location"` not `"thelocation"`. Also, `"location1.InHouse"` is not a valid value for this enum. – Helen Feb 09 '21 at 07:22
  • That is correct @Helen, fixed that. But the question still maintains, what to do for the '.' in the enum value ´location1.Outdoor2´. Changing the char from '.' to '_' would resolve this, but the it would go against the spec. – Madax Feb 09 '21 at 08:25
  • Dots are perfectly valid in enum values in OpenAPI Specification. If the correct JSON payload also results in the same problem, the problem might be with the (de)serializer and/or annotations. Maybe someone with .NET knowledge can comment on this. – Helen Feb 09 '21 at 08:54
  • Right @Helen, that is a minor issue, because i masked this of a ral example... Edit: I also think it is (de)serialization problem, I am using .netcore 3.1 with the standard "System.Text.Json.Serialization" – mfabruno Feb 09 '21 at 09:21

1 Answers1

1

So since I didn't get any help I decided to investigate and found a workaround solution...

I think the problem is that newtonsoft is not correctly parsing nullable enums. So I did a new stringenumconverter that takes that into account when reading the JSON, since their code is open source I could do it:

public class NullableStringEnumConverter : StringEnumConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        try
        {
            return base.ReadJson(reader, objectType, existingValue, serializer);
        }
        catch
        {
            if (IsNullableType(objectType))
                return null;

            return base.ReadJson(reader, objectType, existingValue, serializer);
        }
    }
}

private static bool IsNullableType(Type t)
{
    if (t == null)
        throw new ArgumentNullException(nameof(t));

    return (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
}
    

With this my location was put to "null" when it could not be found in the enum and if it found in the attribute EnumMember a string equal to the one given it worked, while the rest of the object was well parsed.

mfabruno
  • 131
  • 3
  • 12