json - Kotlinx.Serializer - 创建一个快速的 JSON 发送

标签 json kotlin kotlinx.serialization

我一直在玩 Kotlinx.serialisation。我一直在尝试找到一种使用 Kotlinx.serialisation 的快速方法来创建一个简单的 JSON(主要是将其发送出去),并且代码困惑。

对于一个简单的字符串,例如:

{"Album": "Foxtrot", "Year": 1972}

我一直在做的是这样的:
val str:String = Json.stringify(mapOf(
        "Album" to JsonPrimitive("Foxtrot"),
        "Year" to JsonPrimitive(1972)))

这远不是很好。我的元素大多是原始的,所以我希望我有这样的东西:
val str:String = Json.stringify(mapOf(
   "Album" to "Sergeant Pepper",
   "Year" to 1967))

此外,我很高兴有一个带有嵌套 JSON 的解决方案。就像是:
Json.stringify(JsonObject("Movies", JsonArray(
   JsonObject("Name" to "Johnny English 3", "Rate" to 8),
   JsonObject("Name" to "Grease", "Rate" to 1))))

那会产生:
{
  "Movies": [
    {
      "Name":"Johnny English 3",
      "Rate":8
    },
    {
      "Name":"Grease",
      "Rate":1
    }
  ]
}

(不一定美化,甚至更好)

有这样的吗?

备注 : 使用序列化器很重要,而不是直接的字符串,例如
"""{"Name":$name, "Val": $year}"""

因为连接字符串是不安全的。任何非法字符都可能会破坏 JSON!我不想处理转义非法字符:-(

谢谢

最佳答案

这组扩展方法是否给你你想要的?

@ImplicitReflectionSerializer
fun Map<*, *>.toJson() = Json.stringify(toJsonObject())

@ImplicitReflectionSerializer
fun Map<*, *>.toJsonObject(): JsonObject = JsonObject(map {
    it.key.toString() to it.value.toJsonElement()
}.toMap())

@ImplicitReflectionSerializer
fun Any?.toJsonElement(): JsonElement = when (this) {
    null -> JsonNull
    is Number -> JsonPrimitive(this)
    is String -> JsonPrimitive(this)
    is Boolean -> JsonPrimitive(this)
    is Map<*, *> -> this.toJsonObject()
    is Iterable<*> -> JsonArray(this.map { it.toJsonElement() })
    is Array<*> -> JsonArray(this.map { it.toJsonElement() })
    else -> JsonPrimitive(this.toString()) // Or throw some "unsupported" exception?
}

这允许您传入 Map在其中包含各种类型的键/值,并返回它的 JSON 表示。在映射中,每个值都可以是原始值(字符串、数字或 bool 值)、空值、另一个映射(表示 JSON 中的子节点)或上述任何一个的数组或集合。

您可以按如下方式调用它:
val json = mapOf(
    "Album" to "Sergeant Pepper",
    "Year" to 1967,
    "TestNullValue" to null,
    "Musicians" to mapOf(
        "John" to arrayOf("Guitar", "Vocals"),
        "Paul" to arrayOf("Bass", "Guitar", "Vocals"),
        "George" to arrayOf("Guitar", "Sitar", "Vocals"),
        "Ringo" to arrayOf("Drums")
    )
).toJson()

如您所愿,这将返回以下未美化的 JSON:
{"Album":"Sergeant Pepper","Year":1967,"TestNullValue":null,"Musicians":{"John":["Guitar","Vocals"],"Paul":["Bass","Guitar","Vocals"],"George":["Guitar","Sitar","Vocals"],"Ringo":["Drums"]}}

您可能还想为其他一些类型添加处理,例如日期。

但是我可以检查一下您是否要以这种方式在代码中手动构建 JSON,而不是为所有 JSON 结构创建数据类并以这种方式序列化它们吗?我认为这通常是处理这类事情的更标准的方式。尽管您的用例可能不允许这样做。

还值得注意的是,代码必须使用ImplicitReflectionSerializer注释,因为它使用反射来确定每个位使用哪个序列化器。这仍然是实验性功能,将来可能会改变。

关于json - Kotlinx.Serializer - 创建一个快速的 JSON 发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55417112/

相关文章:

php - 如何在 PHP 中回显 JSON

javascript - 如何使用 JavaScript 中的索引浏览嵌套 JSON 文件?

json - kotlinx反序列化: different types && scalar && arrays

android - X 类不是抽象的,也没有实现 android.os.Parcelable 中定义的 fun writeToParcel()

android - kotlinx.serialization.SerializationException : Serializer for class 'MultiPartFormDataContent' is not found

android - 使用 Retrofit 处理变量 JSON

java - 返回 JSON 的 Spring Restful Web 服务

android - Firebase - 未找到 GetTokenResult、getExpirationTimestamp()

Android Room 数据库数据未插入?

Android 不显示所有通知