如何在 Kotlin 中将字符串转换为 JSONObject?

61

我需要将字符串{\"name\":\"test name\", \"age\":25}转换为JSONObject


这个URL可能是你的一个好起点:https://dev59.com/A1gQ5IYBdhLWcg3w-o5w - PacificNW_Lover
取决于JSONObject的类型,对于org.json,请参见https://stleary.github.io/JSON-java/。 - F. George
2
后端用什么?Java 还是 JS? - glee8e
4个回答

64

也许我误解了问题,但听起来你已经在使用org.json,这就引发了一个问题,为什么要这样做

val answer = JSONObject("""{"name":"test name", "age":25}""")

这不是最好的方法吗?JSONObject内置功能有什么问题吗?


4
你是否使用 Kotlin 测试了你的示例?如果是,你使用的库的版本是什么?如果你尝试使用 JSONObject 版本 org.json:json:20200518,你会发现 JSONObject 中没有使用字符串对象作为参数的构造函数。 - Alexandre V.
是的,实际上,考虑到答案是在2017年提供的,我相信在过去的三年里已经发生了很多变化。然而,JSON版本的链接在原帖的评论中。这里是一个直接链接到Javadoc的网址:https://stleary.github.io/JSON-java/org/json/JSONObject.html - Ryba
我刚刚拉取了20200518版本的源代码,并且发现它仍然很好地支持字符串构造函数。请查看https://github.com/stleary/JSON-java/blob/8e5b516f2bab9b81098ef57a7e84076c28441428/JSONObject.java上的第405行。 - Ryba

48
val rootObject= JSONObject()
rootObject.put("name","test name")
rootObject.put("age","25")

7
这个回答假设你已经知道字段和值,如果没有解析字符串,提问者就不可能知道这些。 - Ionoclast Brigham
3
这个回答怎么得到这么多赞?!它并没有回答问题。输入数据应该是一个JSON字符串,这个例子展示了如何逐个字段地构建一个新的JSONObject。 - Alexandre V.
2
我知道这并没有回答楼主的问题,但这确实帮助了我理解如何轻松地将我的数据对象转换为JSON,而无需向我的项目添加另一个库。 - lasec0203

18

你可以使用https://github.com/cbeust/klaxon 库。

val parser: Parser = Parser()
val stringBuilder: StringBuilder = StringBuilder("{\"name\":\"Cedric Beust\", \"age\":23}")
val json: JsonObject = parser.parse(stringBuilder) as JsonObject
println("Name : ${json.string("name")}, Age : ${json.int("age")}")

结果:

Name : Cedric Beust, Age : 23

2
如果您将使用此对象作为API方法的结果,则更喜欢使用此方式,因为klaxon中的JsonObject知道如何将自身序列化回Json。 - Andrew Kovalenko
2
Parser()已被弃用,请使用Parser.default()代替。 - Mugen

4
以上做法有点危险:它们未解决非法字符的问题。 它们也没有进行转义...我们不想自己进行转义吧?
这是我所做的。虽然不够简洁明了,但您只需要执行一次。
class JsonBuilder() {
    private var json = JSONObject()

    constructor(vararg pairs: Pair<String, *>) : this() {
        add(*pairs)
    }

    fun add(vararg pairs: Pair<String, *>) {
        for ((key, value) in pairs) {
            when (value) {
                is Boolean -> json.put(key, value)
                is Number -> add(key, value)
                is String -> json.put(key, value)
                is JsonBuilder -> json.put(key, value.json)
                is Array<*> -> add(key, value)
                is JSONObject -> json.put(key, value)
                is JSONArray -> json.put(key, value)
                else -> json.put(key, null) // Or whatever, on illegal input
            }
        }
    }

    fun add(key: String, value: Number): JsonBuilder {
        when (value) {
            is Int -> json.put(key, value)
            is Long -> json.put(key, value)
            is Float -> json.put(key, value)
            is Double -> json.put(key, value)
            else -> {} // Do what you do on error
        }

        return this
    }

    fun <T> add(key: String, items: Array<T>): JsonBuilder {
        val jsonArray = JSONArray()
        items.forEach {
            when (it) {
                is String,is Long,is Int, is Boolean -> jsonArray.put(it)
                is JsonBuilder -> jsonArray.put(it.json)
                else -> try {jsonArray.put(it)} catch (ignored:Exception) {/*handle the error*/}
            }
        }

        json.put(key, jsonArray)

        return this
    }

    override fun toString() = json.toString()
}

很抱歉,我可能不得不削减一些本来是我的代码中独特的类型,所以我可能会破坏一些东西——但是这个想法应该很清楚。

你可能已经知道,在 Kotlin 中,“to” 是一个中缀方法,可以将两个对象转换为 Pair。因此,你可以像这样简单地使用它:

   JsonBuilder(
      "name" to "Amy Winehouse",
      "age" to 27
   ).toString()

但你可以做更可爱的事情:

JsonBuilder(
    "name" to "Elvis Presley",
    "furtherDetails" to JsonBuilder(
            "GreatestHits" to arrayOf("Surrender", "Jailhouse rock"),
            "Genre" to "Rock",
            "Died" to 1977)
).toString()

1
这个解决方案也是无效的。它展示了如何逐个字段地构建JSONObject。 - Alexandre V.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接