Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swagger shows Mongo ObjectId as complex JSON instead of String

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:

enter image description here

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.

like image 929
redent84 Avatar asked Nov 21 '25 02:11

redent84


1 Answers

For OpenApi (Swagger 3.0) and SpringDoc the following global configuration could be used.

static {
     SpringDocUtils.getConfig().replaceWithSchema(ObjectId.class, new StringSchema());
}
like image 170
vzhemevko Avatar answered Nov 22 '25 15:11

vzhemevko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!