Kotlinx.Serializer - 创建快速 JSON 发送
Kotlinx.Serializer - Create a quick JSON to send
我一直在玩 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
并在其中传递各种类型的 keys/values,并返回它的 JSON 表示。在映射中,每个值可以是原始值(字符串、数字或布尔值)、null、另一个映射(表示 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()
这个returns下面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
注释,因为它使用反射来确定每个位使用哪个序列化程序。这仍是实验性功能,将来可能会发生变化。
我一直在玩 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
并在其中传递各种类型的 keys/values,并返回它的 JSON 表示。在映射中,每个值可以是原始值(字符串、数字或布尔值)、null、另一个映射(表示 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()
这个returns下面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
注释,因为它使用反射来确定每个位使用哪个序列化程序。这仍是实验性功能,将来可能会发生变化。