is there a way to automatically map a javascript j...
# javascript
a
is there a way to automatically map a javascript json object to a
@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 scenario
I ended up creating new functions marked with
@JsExport
, which take
dynamic
as params and doing the mapping manually
a
Could you please share your use case in a little bit more detail (code snippets are welcome)? Without more context (and code), it's a bit hard to understand what you are looking for.
1
a
sure. My front end is Compose Web (kotlin). it holds some data in my
MyDataClass
data class. I send it to my server using ktor + the serialization lib:
Copy code
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:
Copy code
<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:
Copy code
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:
Copy code
@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?
a
Oh, I see. Thank you so much for the explanation. Now it's much more clear. So, you need to somehow create the
MyDataClass
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:
Copy code
// 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)
}
Copy code
// 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()
}
So, you don't need to have any mappings from raw objects to you data. classes
@Alex Styl, could this option work for you?
a
I think so. will give it a go next time i come across the same issue. thanks