动态 Kotlin/Js 对象转换为普通 JavaScript 对象的简单方法是什么?

5
例如,我们有这样的结构:
data class Item(
        val city: String,
        val name: String
)

val structure = mapOf("items" to listOf(
                Item("NY", "Bill"),
                Item("Test", "Test2"))

)

我想在Javascript中获取此对象:

var structure = {
  "items": [
    {
      "city": "NY",
      "name": "Bill"
    },
    {
      "city": "Test",
      "name": "Test2"
    }
  ]
}

我们如何将Kotlin中的map转换为Javascript中具有相同结构的dynamic类型?

我只找到了这种明确的方式:

fun Map<String, Any>.toJs(): dynamic {
    val result: dynamic = object {}

    for ((key, value) in this) {
        when (value) {
            is String -> result[key] = value
            is List<*> -> result[key] = (value as List<Any>).toJs()
            else -> throw RuntimeException("value has invalid type")
        }
    }

    return result
}

fun List<Any>.toJs(): dynamic {
    val result: dynamic = js("[]")

    for (value in this) {
        when (value) {
            is String -> result.push(value)
            is Item -> result.push(value.toJs())
            else -> throw RuntimeException("value has invalid type")
        }
    }

    return result
}

fun Item.toJs(): dynamic {
    val result: dynamic = object {}

    result["city"] = this.city
    result["name"] = this.name

    return result
}

我知道也可以使用序列化/反序列化来实现这一点,但我认为它会更慢且有一些额外的开销。
有人知道将Kotlin的object转换为普通Javascript的objectdynamic Kotlin类型)的简单方法吗?

也许是 .asDynamic()? - deviant
.asDynamic only reinterprets this value as a value of the dynamic type - kurt
@kurt 你找到什么了吗? - IARI
2个回答

1
您可以使用这个简单的函数来实现。
inline fun <I> objectOf(
    jsonObject: I = js("new Object()").unsafeCast<I>(),
    writer: I.() -> Unit
): I {
    writer(jsonObject)
    return jsonObject
}

使用方法:

interface Structure {
    var items: Array<Item>

    interface Item {
        var city: String
        var name: String
    }
}


fun main() {
        val structure0 = objectOf<dynamic> {
            items = arrayOf<dynamic>(
                objectOf {
                    city = "NY"
                    name = "Bill"
                    orAnything = "Literly, anything!"
                },
                objectOf { city = "Test"; name = "Test2" }
            )
        }
        println(JSON.stringify(structure0))
        // {"items":[{"city":"NY","name":"Bill","orAnything":"Literly, anything!"},{"city":"Test","name":"Test2"}]}
    
        val structure1 = objectOf<Structure> {
            items = arrayOf(
                objectOf {
                    city = "NY"
                    name = "Bill"
    //                orAnything = "Literly anything" // Compile time Error: Unresolved reference: orAnything
                },
                objectOf {
                    city = "Test"
                    name = "Test2"
                }
            )
        }
    
        println(JSON.stringify(structure1))
        // {"items":[{"city":"NY","name":"Bill"},{"city":"Test","name":"Test2"}]}
    
        val structure2 = objectOf(structure1) {
            items.forEach {
                it.city = "Khartoum"
            }
        }
        println(JSON.stringify(structure2))
        // {"items":[{"city":"Khartoum","name":"Bill"},{"city":"Khartoum","name":"Test2"}]}
    
        val structure3 = objectOf(structure0) {
            items.unsafeCast<Array<dynamic>>().forEach {
                it.name = "Shalaga44"
            }
        }
        println(JSON.stringify(structure3))
        //{"items":[{"city":"NY","name":"Shalaga44","orAnything":"Literly, anything!"},{"city":"Test","name":"Shalaga44"}]}
    
    }

不是从地图上来的,但似乎可用。谢谢 =) - kurt

-2

如果我没有真正理解你的问题,那么请原谅我,如果这不能帮助你。 就我个人而言,我喜欢使用Klaxon: https://github.com/cbeust/klaxon

您可以编写自己的反射工具来迭代数据类中的所有属性并将它们转换为JSON。


1
谢谢,但这不是我需要的。 我想获得纯粹的JavaScript对象,其结构如上所述,但不需要序列化/反序列化。 我在帖子中指出了这样转换的示例。 - kurt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接