【问题标题】:How to serialize a Map to JSON string via JSON.stringify in kotlin JS?如何通过 kotlin JS 中的 JSON.stringify 将 Map 序列化为 JSON 字符串?
【发布时间】:2018-02-26 10:53:02
【问题描述】:

我的示例代码如下:

fun main(args: Array<String>) {
    val testData = mapOf<String, Any>(
        "name" to "albert",
        "age" to 26,
        "work" to listOf("1", "2", "3")
    )

    var value = JSON.stringify(testData, { _, value -> value.toString() }, 2)

    println(value)
}

结果是"{name=albert, age=26, work=[1, 2, 3]}"。 似乎它错过了属性名称和字符串值周围的所有双引号。

我使用的是KotlinJS 而不是Kotlin

那么,如何解决呢?

【问题讨论】:

  • 我在 kotlin 上玩了一段时间......不是 100% 确定我是对的,但实际上这段代码正在做的是调用 java Map.toString(),然后将此值赋予 js @987654328 @,所以"{name=albert, age=26, work=[1, 2, 3]}" 不是json,但是map.toString() 和JSON.stringify 只是在这个字符串周围加上引号。您可以做的是在 java 中使用 jackson 或 gson 转换测试数据,然后忘记 JSON,或者您可以尝试 github.com/Kotlin/kotlinx.serialization 也看看 discuss.kotlinlang.org/t/kotlin-serialization/2063/25
  • @varren 非常感谢您的帮助。这是一个完整的 KotinJS 环境,所以不能从 JVM 世界中受益 :( 我试过 println(JSON.stringify(testData.toString())),仍然没有引号。根据你分享的帖子,似乎内置序列化的东西还没有登陆 KotlinJS 世界。正如你所说,我会调查第 3 方库,谢谢。

标签: javascript json kotlin kotlin-js-interop


【解决方案1】:

实际上,您并没有得到JSON.stringify 的结果。相反,您会得到kotlin.collections.HashMap.toString 的结果。原因如下:您将 lambda 作为第二个参数传递:{ _, value -&gt; value.toString() }。这会将您的整个地图转换为字符串,使用 toString() 函数。而HashMap.toString 函数被定义为生成这样的字符串,它不是 JSON 字符串。您应该使用没有第二个和第三个参数的JSON.stringify。但是,这不会很好,产生Uncaught TypeError: Converting circular structure to JSON 错误。原因如下:JSON.stringify 不是 Kotlin 语言的一部分,它只是一个名为 JSON 的原生浏览器对象的 typed definitionHashMap 不是一个空的 JavaScript 对象,它允许使用任何类型的对象作为键,它暴露了类似 Java 的 Map API,这在 JavaScript 对象中是不可用的。所以,HashMap 不适合你的工作。有几种解决方案:

  1. 您可以等到我们发布 Kotlin 多平台序列化,请参阅 the corresponding discussion。该 API 能够理解 Kotlin 类并将其正确转换为 JSON。

  2. 不要使用 Kotlin 映射和列表,使用原生 JavaScript 实体,例如 json 和纯数组。您的示例可以通过以下方式重写:

    导入 kotlin.js.json

    fun main(args: Array<String>) {
        val testData = json(
            "name" to "albert",
            "age" to 26,
            "work" to arrayOf("1", "2", "3")
        )
    
        var value = JSON.stringify(testData)
    
        println(value)
    }
    

【讨论】:

  • 好多了,适合我目前的使用,谢谢!等你们发布:)
  • 我们可以遍历 Json 对象的属性吗?
  • 你可以调用Object.keys()或者Object.getOwnPropertyNames(),或者作为内联JS或者将这些方法定义为外部。
  • 谢谢。但那些是 JS 方法对吗?我得到的数据是kotlin.js.Json,我尝试使用(data as dynamic).keys(),导致错误:此位置不允许动态类型:(
  • 正确的语法是data.asDynamic().keys()。但这不起作用,因为keys() 不是成员函数。您应该编写类似 js("Object.keys(data)") 或 external class Object {companion object { fun keys(value: Any): Array } } Object.keys(data) 之类的东西
【解决方案2】:

这个答案比之前接受的答案晚了几年,但我(Kotlin 的新手)遇到了同样的问题,并想出了一个很好的方法来实现这一点。

  1. 假设您有一个已填充的地图
  2. 创建一个空的 js 对象(对我来说似乎很 hacky,但这是 Kotlin 到 JS)
  3. 遍历地图的“toList”方法,该方法提供了一对
  4. 将每一对插入到 js 对象中
  5. 获取 js JSON api
  6. 并调用“stringify”提供您的 js 对象。记得最后要“toString”

    val data: Map<String, Any?> = mapOf() // 1
    val export = js("{}") // 2
    for (pair: Pair<String, Any?> in data.toList()) { // 3
        export[pair.first] = pair.second // 4
    }
    val jsoner = js("JSON") // 5
    return jsoner.stringify(export).toString() // 6
    

【讨论】:

    猜你喜欢
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    相关资源
    最近更新 更多