Search code examples
json.netasp.net-web-api2asp.net-core-2.0asp.net-core-2.1swashbuckle

JsonConverter and Swashbuckle - Approach for decorating a swagger


I'm playing around and developed a simple custom JsonConverter that takes a min and max temperature and have decorated my model class as follows and validates that the temperature falls in that range.

[JsonConverter(typeof(TemperatureConverter), 5, 10)]
public int Temperature { get; set; }

This is all good but I'm wondering what's the approach to best output the correct decoration in my swagger file generated by swashbuckle... like so:

name: Temperature
          schema:
            type: integer
            minimum: 5
            maximum: 10

I know this is a trivial example, but it's more the approach to tying JsonConverter to the generation of the swagger I'm interested in.

I'm currently looking at ISchemaFilter but can't see how I can get the type of converter that decorates the property.

Thanks


Solution

  • You have to be at the parent schema level, looking at it's properties. By the time it gets to the property itself, it is too late, as there is no link back to the parent class.

    I was using a custom attribute, not JsonConverter, but something like this should work for detecting the attribute.

        public class TemperatureSchemaFilter : ISchemaFilter
        {
            public void Apply(Schema schema, SchemaFilterContext context)
            {
                var converterProperties = context.SystemType.GetProperties().Where(
                    prop => prop.CustomAttributes.Select(
                        attr => attr.AttributeType == typeof(JsonConverterAttribute)).Any()
                    ).ToList();
                foreach (var converterProperty in converterProperties)
                {
                    var converterAttribute = (JsonConverterAttribute)Attribute.GetCustomAttribute(converterProperty.PropertyType, typeof(JsonConverterAttribute));
                    if (converterAttribute.ConverterType != typeof(TemperatureConverter)) continue;
                    Schema propertySchema = null;
                    try
                    {
                        propertySchema = schema.Properties.First(x => x.Key.ToLower().Equals(converterProperty.Name.ToLower())).Value;
                    }
                    catch (Exception)
                    {
                        continue;
                    }
    
                    if (propertySchema == null) continue;
                    propertySchema.Minimum = (double) converterAttribute.ConverterParameters[0];
                    propertySchema.Maximum = (double) converterAttribute.ConverterParameters[1];
                }
            }
        }
    

    Unfortunately my environment is currently hosed, so I can't test it out, but I think this is the way to go.