64

I need to convert a string {\"name\":\"test name\", \"age\":25} to a JSONObject

3

5 Answers 5

66

Perhaps I'm misunderstanding the question but it sounds like you are already using org.json which begs the question about why

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

wouldn't be the best way to do it? What was wrong with the built in functionality of JSONObject?

Sign up to request clarification or add additional context in comments.

3 Comments

Did you test your example using Kotlin? If yes, what version of the library did you use? If you try that with JSONObject version org.json:json:20200518 you'll see that the contructor with a String object is not available in the JSONObject.
Yes actually and given that the answer was provided back in 2017 I'm sure there have been quite a number of changes that have taken place over the past 3 years. However, the link to which json version is in the original post's comment. Here is a direct link to the javadoc stleary.github.io/JSON-java/org/json/JSONObject.html
I just pulled up the 20200518 version of the source code and see that it does still support the string constructor just fine. Line 405 on github.com/stleary/JSON-java/blob/…
48
val rootObject= JSONObject()
rootObject.put("name","test name")
rootObject.put("age","25")

3 Comments

This answer assumes you already know the fields and values, which the asker can't know if they haven't parsed the string yet.
How did this answer get so many upvotes!? It does not answer the question. The input data should be a JSON string, this example shows how to build a new JSONObject field by field.
I know this doesn't answer the OP's question, but this did help me understand how to easily create JSON out of my data objects without adding another lib to my project.
18

You can use https://github.com/cbeust/klaxon library.

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")}")

Result :

Name : Cedric Beust, Age : 23

2 Comments

This way is more preferable if you going to use this object as a result of API method since JsonObject from klaxon knows how to serialize itself back to Json.
Parser() is deprecated, use Parser.default() instead
4

The approaches above are a bit dangerous: They don't provide a solution for illegal chars. They don't do the escaping... And we hate to do the escaping ourselves, don't we?

So here's what I did. Not that cute and clean but you have to do it only once.

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()
}

Sorry, might have had to cut off types that were unique to my code so I might have broken some stuff - but the idea should be clear

You might be aware that in Kotlin, "to" is an infix method that converts two objects to a Pair. So you use it simply like this:

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

But you can do cuter things:

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

1 Comment

This solution is also not valid. It's showing how to build a JSONObject field by field.
1

Kotlin Serialization

import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject    

return Json.decodeFromString<JsonObject>("""{"name":"test name", "age":25}""")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.