Alex Styl
12/17/2024, 1:42 PM@Serialized
data class or do i need to do the mapping on my own?
context: I have a kotlin library with functions that take data classes as params. I tried using it as is from javascript and pass javascript objects but it didn't work (getting all sorts of errors), so I am assuming the types are wrong. so my assumption is someone needs to do the mapping and was wondering if there is a baked in way for this scenarioAlex Styl
12/17/2024, 1:55 PM@JsExport
, which take dynamic
as params and doing the mapping manuallyArtem Kobzar
12/17/2024, 4:05 PMAlex Styl
12/18/2024, 3:51 PMMyDataClass
data class.
I send it to my server using ktor + the serialization lib:
val response = <http://httpClient.post|httpClient.post>("/api/process") {
contentType(ContentType.Application.Json)
val bodyString = Json.encodeToString<MyDataClass>(data)
setBody(bodyString)
}
My Server is an express js server:
<http://app.post|app.post>('/api/process', async (req, res) => {
const data = req.body;
I want to process that data using kotlin, so i made a kotlin npm package with a related function:
fun processData(data: MyDataClass) = TODO()
The question is. How I do call this kotlin function from javascript without having type mismatches?
I tried marking it with @JsExport
and calling it directly in javascript, passing the javascript object as parameter, but my kotlin code was crashing with some weird obscure errors.
What I found works is create a function with dynamic parameter and do the mapping mannually:
@JsExport
fun processData(data: dynamic) {
val myClassData : MyDataClass = ...
return processData(myClassData)
}
fun processData(data: MyDataClass) = TODO()
Do I need to do this mapping manually or is there an other way to do it?Artem Kobzar
12/18/2024, 5:49 PMMyDataClass
from the JSON parsed on the express side.
One of the options you can do (ofc if your express controller is supposed to be used only with the MyDataClass
) is to tell express not to parse the request body (so it will be a text) and, from the Kotlin side, deserialize the class using kotlinx.serialization. As a sketch, it would look like this:
// Express side
// Variant 1
app.use(express.json()); // You can remove the line if all of your controllers work only with the Kotlin data
// Variant 2
app.post('/api/process', express.text({ type: '*/*' }), async (req, res) => { // If only several routes should be parsed by kotlinx.serialization
const data = req.body;
// And depends on the variants below, your route body would look like this:
async (req, res) => {
processData(parseMyDataClass(req.body))
}
// Or like this
async (req, res) => {
processData(req.body)
}
// Kotlin side
// You can do like this
@JsExport
fun parseMyDataClass(data: String): MyDataClass = Json.decodeFromString<MyDataClass>(data)
@JsExport
fun processData(data: MyDataClass) = TODO()
// Or like this
@JsExport
fun processData(data: String) {
val myData = Json.decodeFromString<MyDataClass>(data)
TODO()
}
Artem Kobzar
12/18/2024, 5:50 PMArtem Kobzar
12/18/2024, 5:50 PMAlex Styl
12/20/2024, 3:51 AM