Как сериализовать строку Map to JSON через JSON.stringify в Kotlin JS?

Мой пример кода ниже:

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

Итак, как это решить?

4 ответа

Решение

На самом деле, вы не получите результат JSON.stringify, Вместо этого вы получите результат kotlin.collections.HashMap.toString, Причина в следующем: вы передаете лямбду в качестве второго параметра: { _, value -> value.toString() }, Это преобразует всю вашу карту в строку, используя, toString() функция. А также HashMap.toString Функция определена для генерации такой строки, которая не является строкой JSON. Вы должны были использовать JSON.stringify без второго и третьего параметра. Тем не менее, это не будет работать, производя Uncaught TypeError: Converting circular structure to JSON ошибка. Причина в следующем: JSON.stringify не является частью языка Kotlin, это просто типизированное определение нативного объекта браузера, называемого JSON. HashMap не пустой объект JavaScript, он позволяет использовать любые типы объектов в качестве ключей, он предоставляет Java-подобный Map API, который недоступен в объекте JavaScript. Так, HashMap не подходит для того, что вы делаете. Есть несколько решений:

  1. Вы можете подождать, пока мы не опубликуем мультиплатформенную сериализацию Kotlin, смотрите соответствующее обсуждение. Этот 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)
    }
    

В последних версиях kotlinx-serialization используйтеencodeToDynamic:

      val json = Json.encodeToDynamic(map)

Результатом является динамический объект, содержащий объект JSON. У этого подхода есть некоторые ограничения — например, все ключи карты должны быть примитивами или перечислениями.Longзначения имеют максимальное значение. См. документы для более подробной информации.

Этот ответ приходит через несколько лет после предыдущего принятого ответа, но я (новичок в Kotlin) столкнулся с той же проблемой и нашел хороший способ добиться этого.

  1. Предположим, у вас есть заполненная карта
  2. Создайте пустой объект js (мне кажется хакерским, но это Kotlin для JS)
  3. перебирать метод "toList" вашей карты, который предоставляет Pair
  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
    

Если вы хотите просто получить действительную строку JSON из Kotlin, вы можете сделать это, используя kotlinx.serialization.json:

      Json.encodeToString(map)

Если вы хотите красиво упорядочить Kotlin Map, который можно отобразить в виде красивого JSON в <pre>тег, вы можете сделать:

      val jsonString = Json.encodeToString(map)            // 1
val jsonObject = JSON.parse<JsonObject>(jsonString)  // 2
return JSON.stringify(jsonObject, null, 2)           // 3
  1. Сериализуйте карту в строку JSON, используя сериализацию Kotlin.
  2. Разобрать строку JSON в объект Javascript
  3. Довольно упорядочить объект Javascript
Другие вопросы по тегам