springdoc-openapi icon indicating copy to clipboard operation
springdoc-openapi copied to clipboard

Support custom Serializer/Converts not only with paths sections also needed for schema definitions

Open melistik opened this issue 1 year ago • 0 comments

We use in our application TSID. It's similar to snowflake or other timebased sequence generators. The object is build for use outside "java-world" as string representation that will be easily get converted back to a TSID object that holds time information plus a random number for uniqueness.

I've implemented custom Converts + a Jackson Module to have a convenient way of use. It's also published open-source. Asper read in the ticket #1534 Converters are supported after a fix for path objects but still it's not considered for schema definitions.

@RequestMapping(path = "/tile", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
public interface TileApi {

    @GetMapping(
            path = "/tile/{id}",
            produces = MimeTypeUtils.APPLICATION_JSON_VALUE
    )
    Tile get(@Parameter(description = "id of tile", required = true)
             @PathVariable("id") TSID id);
}

@Data
public class Tile implements Serializable {

    private TSID id;

    private String name;

    private String description;
}

The output of the openApi definition looks like this without a custom converter

openapi: 3.0.1
info:
  title: SampleAPI
paths:
  /tile/tile/{id}:
    get:
      tags:
      - tile
      operationId: get
      parameters:
      - name: id
        in: path
        description: id of tile
        required: true
        schema:
          $ref: "#/components/schemas/TSID"
components:
  schemas:
    TSID:
      type: object
      properties:
        unixMilliseconds:
          type: integer
          format: int64
        instant:
          type: string
          format: date-time
    Tile:
      type: object
      properties:
        id:
          $ref: "#/components/schemas/TSID"
        name:
          type: string
        description:
          type: string

After registering a converter

public class TsidConverter implements Converter<String, TSID> {

    @Nullable
    @Override
    public TSID convert(String value) {
        return TSID.isValid(value) ? TSID.from(value) : null;
    }
}

the paths sections switch to string but schema definition stays the same

paths:
  /tile/tile/{id}:
    get:
      tags:
      - tile
      operationId: get
      parameters:
      - name: id
        in: path
        description: id of tile
        required: true
        schema:
          type: string

as mentioned above i've registered also a jackson module to stick serializing to string.

public class TsidSerializer extends StdSerializer<TSID> {

    public TsidSerializer() {
        super(TSID.class);
    }


    @Override
    public void serialize(TSID tsid, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(tsid.toString());
    }
}
public class TsidDeserializer extends StdDeserializer<TSID> {

    public TsidDeserializer() {
        super(TSID.class);
    }


    @Override
    public TSID deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
        String value = jsonParser.getValueAsString();
        if (StringUtils.hasText(value) && TSID.isValid(value)) {
            return TSID.from(value);
        }
        return null;
    }
}
public class TsidModule extends SimpleModule {

    public TsidModule() {
        super(TsidModule.class.getSimpleName(), new Version(1, 0, 0, null, null, null),
                Map.of(TSID.class, new TsidDeserializer()),
                List.of(new TsidSerializer()));
    }
}

how to configure it correctly, so that the schema definition of Tile object looks like:

components:
  schemas:
    Tile:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string

example uses newest version of springdoc-openapi 2.6.0 + springdoc-openapi-starter-webmvc-api

thx in advance for your help. Not sure if it's a bug or new feature...

melistik avatar Aug 28 '24 04:08 melistik