首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Kotlinx.Serializer -创建一个要发送的快速JSON

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

Stack Overflow用户
提问于 2019-03-29 12:06:33
回答 1查看 2.8K关注 0票数 5

我一直在和Kotlinx.serialisation玩。我一直试图找到一种快速的方法来使用Kotlinx.serialisation来创建一个简单的JSON (主要是用来发送出去的),并且尽量减少代码的杂乱。

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

代码语言:javascript
复制
{"Album": "Foxtrot", "Year": 1972}

我一直在做的事情是:

代码语言:javascript
复制
val str:String = Json.stringify(mapOf(
        "Album" to JsonPrimitive("Foxtrot"),
        "Year" to JsonPrimitive(1972)))

这可不是什么好事。我的元素大多是原始的,所以我希望我有这样的东西:

代码语言:javascript
复制
val str:String = Json.stringify(mapOf(
   "Album" to "Sergeant Pepper",
   "Year" to 1967))

此外,我希望有一个带有嵌套JSON的解决方案。类似于:

代码语言:javascript
复制
Json.stringify(JsonObject("Movies", JsonArray(
   JsonObject("Name" to "Johnny English 3", "Rate" to 8),
   JsonObject("Name" to "Grease", "Rate" to 1))))

这将产生:

代码语言:javascript
复制
{
  "Movies": [
    {
      "Name":"Johnny English 3",
      "Rate":8
    },
    {
      "Name":"Grease",
      "Rate":1
    }
  ]
}

(不一定美化,更好的不是)

有这样的东西吗?

注意事项:重要的是使用序列化程序,而不是直接字符串,例如

代码语言:javascript
复制
"""{"Name":$name, "Val": $year}"""

因为连接字符串是不安全的。任何非法的字符都可能分解JSON!我不想处理逃避非法犯罪的问题。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-29 16:41:08

这组扩展方法是否为您提供了您想要的?

代码语言:javascript
复制
@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表示。在映射中,每个值都可以是原语(字符串、数字或布尔值)、null、另一个映射(表示JSON中的子节点)或上述任何一个数组或集合。

你可以这样称呼它:

代码语言:javascript
复制
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,而不是您想要的修饰:

代码语言:javascript
复制
{"Album":"Sergeant Pepper","Year":1967,"TestNullValue":null,"Musicians":{"John":["Guitar","Vocals"],"Paul":["Bass","Guitar","Vocals"],"George":["Guitar","Sitar","Vocals"],"Ringo":["Drums"]}}

您可能还希望添加其他类型的处理,例如日期。

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

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

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55417112

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档