Project setup
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"
}
]
Issue
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.