Hello. I am trying kotlin serialization to js: ```...
# javascript
f
Hello. I am trying kotlin serialization to js:
Copy code
@Serializable
data class Test(var inner: Map<String, String>)

......

try{
            val str = """
                {
                  "inner" : {
                    "a" : "b"
                  }
                }
            """.trimIndent()

            val parsed = JSON.parse<Test>(str)
            parsed.inner.forEach {
                println(it)
            }
        }catch (e: Throwable){
            println(e.message)
        }
It prints Cannot read property 'iterator' of undefined because inner map is deserializable to object (not to Map). Can you help me?
a
cc @sandwwraith
s
Seems like a bug. Can you file an issue on github.com/Kotlin/kotlinx.serialization ?
f
ok.
Just found the reason: invalid import JSON was not from
kotlinx.serialization
but from
kotlin.core
. May be it should be different names or different method names?
s
@anton.bannykh ?
a
@Fedor Bobin you mean kotlin.js.JSON?
If you do, keep in mind that kotlin.js.JSON.parse is an external declaration. Which means it just describes, what a native JS function does. That means two things. First, it doesn't make sure the resulting value type is correct. It just assumes it is. Second, in order to describe the result of JSON.parse correctly, you should use an
external interface
declaration. Or just
Json
. Or
dynamic
. Most importantly, don't use some Kotlin class, since the compiler will assume it has some extra feature (e.g. methods defined on the protype, some metadata, etc), and there will be nothing like that on the actual Json value, created by the javascript JSON.parse function.
So for example, this works:
Copy code
import kotlin.js.*

external interface Test {
    val inner: Json
}

private fun Json.toMap(): Map<String, String> {
    val map: MutableMap<String, String> = linkedMapOf()
    for (key in js("Object").keys(this)) {
        map.put(key, this[key] as String)
    }
    return map
}

fun main(args: Array<String>) {
    
    val str = """
               {
                 "inner" : {
                   "a" : "b"
                 }
               }
           """.trimIndent()

    try {
           val parsed = JSON.parse<Test>(str)
           parsed.inner.toMap().forEach {
               println(it)
           }
    } catch (t: Throwable) {
        println(t.message)      
    }
}
s
The question was, is it possible to suppress
kotlin.js.JSON
auto-import, because it’s a common issue for kotlinx-serialization-js users
a
Like this:
import kotlinx.serialization.json.JSON
?
s
Seems like when you type
JSON
, idea auto-imports
kotlin.js.JSON
and doesn’t suggest to import
kotlinx.serialization.json.JSON
a
Maybe it would make sense to move kotlinx.serialization.json.JSON to package kotlinx.serialization. This way the statement
import kotlinx.serialization.*
would hide the kotlin.js.JSON
By the way, kotlin.js.JSON is imported by default, meaning you don't have to write a single
import
statement in order to use it (which I personally dislike)
s
that gets the problem even harder
a
We won't be able to change this until 1.3