Affects: 3.0.6
I want to make a REST API using Spring and Kotlin.
plugins {
id("org.springframework.boot") version "3.0.6"
id("io.spring.dependency-management") version "1.1.0"
kotlin("jvm") version "1.8.21"
kotlin("plugin.serialization") version "1.8.21"
kotlin("plugin.spring") version "1.8.21"
}
I have this data class, I want to serialize it using Kotlin serialization
@Serializable
data class Account(
var name: String,
var email: String,
var role: String,
@SerialName("is_active")
var active: Boolean,
var id: String,
@SerialName("created_at")
@Serializable(with = InstantSerializer::class)
var createdAt: Instant = Instant.EPOCH
)
This is my controller that returns an application/json
content :
@RestController
@RequestMapping("/accountExamples")
class AccountExampleController {
@GetMapping
fun getAll(): Flow<Account> = List(2) {
Account(
name = "name $it",
email = "email $it",
role = "role $it",
active = true,
id = "$it",
createdAt = Instant.now()
)
}.asFlow()
}
When I call it, everything is correct :
[
{
"name": "name 0",
"email": "email 0",
"role": "role 0",
"is_active": true,
"id": "0",
"created_at": "2023-04-29T09:34:03.103Z"
},
{
"name": "name 1",
"email": "email 1",
"role": "role 1",
"is_active": true,
"id": "1",
"created_at": "2023-04-29T09:34:03.103Z"
}
]
However, when I want to produce an application/x-ndjson
result using :
@RestController
@RequestMapping("/accountExamples")
class AccountExampleController {
@GetMapping(produces = [APPLICATION_NDJSON_VALUE])
fun getAll(): Flow<Account> = List(2) {
Account(
name = "name $it",
email = "email $it",
role = "role $it",
active = true,
id = "$it",
createdAt = Instant.now()
)
}.asFlow()
}
This is the json result :
{
"name": "name 0",
"email": "email 0",
"role": "role 0",
"active": true,
"id": "0",
"createdAt": "2023-04-29T09:35:12.328055700Z"
}
{
"name": "name 1",
"email": "email 1",
"role": "role 1",
"active": true,
"id": "1",
"createdAt": "2023-04-29T09:35:12.328055700Z"
}
As you can see, Kotlin serialization is not used to serialize objects when I want to produce application/x-ndjson
. Instead of it, Jackson is used.
In this case, if we set the JsonProperty
annotation on a field, the final json will be modified
@Serializable
data class Account(
var name: String,
var email: String,
var role: String,
@SerialName("is_active")
var active: Boolean,
var id: String,
@SerialName("created_at")
@JsonProperty("test") // Jackson annotation here
@Serializable(with = InstantSerializer::class)
var createdAt: Instant = Instant.EPOCH
)
Result :
{
"test": "2023-04-29T09:38:31.009048100Z",
"name": "name 0",
"email": "email 0",
"role": "role 0",
"active": true,
"id": "0"
}
{
"test": "2023-04-29T09:38:31.009048100Z",
"name": "name 1",
"email": "email 1",
"role": "role 1",
"active": true,
"id": "1"
}
Comment From: sdeleuze
Hi, the thing is that Kotlin Serialization support in Spring does not support yet streaming. If you use case is just about finite Flow
serialization, could you please try to extend Spring codec/converter to specify customized mime type? Or do you need streaming support?
Comment From: Distractic
I don't need streaming support for the moment. I was just curious about the use of Kotlin in Spring so I tried it. In my test, I used the maximum of Kotlin component (serializable, coroutine etc.) So, when I see this feature is missing, I created an issue to alert about it because I would like use every Kotlin tools (and Spring) to create a server. Do you think the support of streaming can be implemented in Spring in the future?
Comment From: sdeleuze
It will require Kotlin/kotlinx.serialization#253 to be fixed, so let's keep this issue opened but blocked on this issue.
Comment From: sdeleuze
Superseded by #32074.