Kotlin DSL for creating json objects (without creating garbage)

Do you need a DSL? You lose the ability to enforce String keys, but vanilla Kotlin isn't that bad :)

JSONObject(mapOf(
        "name" to "ilkin",
        "age" to 37,
        "male" to true,
        "contact" to mapOf(
                "city" to "istanbul",
                "email" to "[email protected]"
        )
))

You can use a Deque as a stack to track your current JSONObject context with a single JsonObjectBuilder:

fun json(build: JsonObjectBuilder.() -> Unit): JSONObject {
    return JsonObjectBuilder().json(build)
}

class JsonObjectBuilder {
    private val deque: Deque<JSONObject> = ArrayDeque()

    fun json(build: JsonObjectBuilder.() -> Unit): JSONObject {
        deque.push(JSONObject())
        this.build()
        return deque.pop()
    }

    infix fun <T> String.To(value: T) {
        deque.peek().put(this, value)
    }
}

fun main(args: Array<String>) {
    val jsonObject =
            json {
                "name" To "ilkin"
                "age" To 37
                "male" To true
                "contact" To json {
                    "city" To "istanbul"
                    "email" To "[email protected]"
                }
            }
    println(jsonObject)
}

Example output:

{"contact":{"city":"istanbul","email":"[email protected]"},"name":"ilkin","age":37,"male":true}

Calling json and build across multiple threads on a single JsonObjectBuilder would be problematic but that shouldn't be a problem for your use case.

Tags:

Kotlin