Swagger 之 自定义类型拦截

问题产生

本人从事gis行业,使用NetTopologySuite库时,api 暴露的 dto 中存在地理数据模型,直接转json会很长而且存在循环嵌套问题。server采用aspnetcore webapi ,配置controller时添加JsonSerializerOptions.Converters,以达到dto中的地理模型转换为简洁的数据交换格式(如 wkt)。但是swagger ui出现了问题。

本文目标 :Geometry类型及其子类 -> 在swagger ui中显示为 string


配置json Converters

说明

  • SpatialDataConverter 实现了数据转换,这里不展示全部代码
public class WktJsonConverter<T> : JsonConverter<T> where T : Geometry
{
    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return SpatialDataConverter.WktToGeometry<T>(reader.GetString());
    }
    
    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        var wktJson = SpatialDataConverter.GeometryToWkt(value);
        writer.WriteStringValue(wktJson);
    }
}


//在Startu.cs文件 ConfigureServices 中配置
services.AddControllers().AddJsonOptions(option =>
{
    var converters = option.JsonSerializerOptions.Converters;
    converters.Add(new WktJsonConverter<Point>());
    converters.Add(new WktJsonConverter<Polygon>());
    converters.Add(new WktJsonConverter<LinearRing>());
    converters.Add(new WktJsonConverter<LineString>());
    converters.Add(new WktJsonConverter<MultiPolygon>());
    converters.Add(new WktJsonConverter<Geometry>());
});

swagger ui 问题出现了 这个Polygon类型太长了,也不满足我们预期的wkt格式(string)


解决问题 - ISchemaFilter

//实现 ISchemaFilter
public class GeometrySchemaFilter : ISchemaFilter
{
    private static readonly Dictionary<Type, SchemaChangeType> mapper = new()
    {
        //[类型]=显示
        [typeof(Point)] = new SchemaChangeType("string", "POINT (1 2)"),
        [typeof(Polygon)] = new SchemaChangeType("string", "POLYGON ((1 0,1 1, 0 0 , 1 0))"),
        [typeof(LinearRing)] = new SchemaChangeType("string", "LINEARRING (1 0, 1 1, 0 0, 1 0)"),
        [typeof(LineString)] = new SchemaChangeType("string", "LINESTRING (1 0, 1 1)"),
        [typeof(MultiPolygon)] = new SchemaChangeType("string", "MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2)),((6 3,9 2,9 4,6 3)))"),
        [typeof(Geometry)] = new SchemaChangeType("string", "POINT (1 2)"),
    };

    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (mapper.TryGetValue(context.Type, out var value))
        {
            schema.Properties.Clear();
            schema.Type = value.Type;
            schema.Example = new OpenApiString(value.Value);
        }
    }
}

internal class SchemaChangeType
{
    public SchemaChangeType(string type, string value)
    {
        Type = type;
        Value = value;
    }
    public string Type { get; set; }
    public string Value { get; set; }
}


//AddSwaggerGen中配置
//重新定义example
c.SchemaFilter<GeometrySchemaFilter>();

效果

posted @ 2021-08-06 14:28  辣椒鱼儿酱  阅读(511)  评论(0)    收藏  举报