I have a Kotlin Spring Boot 2.0 project that exposes a @RestController API that returns MongoDB models. For example, this model and controller:
@RestController
@RequestMapping("/api/accounts")
class AccountsController() {
@GetMapping
fun list(): List<Account> {
return listOf(Account(ObjectId(), "Account 1"), Account(ObjectId(), "Account 2"), Account(ObjectId(), "Account 3"))
}
}
@Document
data class Account(
@Id val id: ObjectId? = null,
val name: String
)
These models have ObjectId identifiers, but in the API I want them to be treated as plain String (i.e. instead of a complex JSON, the default behaviour).
To achieve this, I created these components to configure Spring Boot parameter binding and JSON parsing:
@JsonComponent
class ObjectIdJsonSerializer : JsonSerializer<ObjectId>() {
override fun serialize(value: ObjectId?, gen: JsonGenerator?, serializers: SerializerProvider?) {
if (value == null || gen == null) return
gen.writeString(value.toHexString())
}
}
@JsonComponent
class ObjectIdJsonDeserializer : JsonDeserializer<ObjectId>() {
override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): ObjectId? {
if (p == null) return null
val text = p.getCodec().readTree<TextNode>(p).textValue()
return ObjectId(text)
}
}
@Component
class StringToObjectIdConverter : Converter<String, ObjectId> {
override fun convert(source: String): ObjectId? {
return ObjectId(source)
}
}
So far this works as intended, calls to the API return this JSON:
[
{
"id": "5da454f4307b0a8b30838839",
"name": "Account 1"
},
{
"id": "5da454f4307b0a8b3083883a",
"name": "Account 2"
},
{
"id": "5da454f4307b0a8b3083883b",
"name": "Account 3"
}
]
The problem comes when integrating Swagger into the project, the documentation shows that calling this method returns a complex JSON instead of a plain String as the id property:

Adding @ApiModelProperty(dataType = "string") to the id field made no difference, and I can't find a way to solve it without changing all the id fields in the project to String. Any help would be appreciated.
For OpenApi (Swagger 3.0) and SpringDoc the following global configuration could be used.
static {
SpringDocUtils.getConfig().replaceWithSchema(ObjectId.class, new StringSchema());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With