Support custom Serializer/Converts not only with paths sections also needed for schema definitions
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...