Skip to content

JSON Minify — Kotlin source

Remove all whitespace from JSON for the most compact serialization. Validates as it minifies, runs entirely in your browser, with a shareable link to your exact input.

This is the Kotlin implementation — the same logic the interactive tool runs, in a shareable, citable form.

// json-minify — compact JSON to its smallest valid form. Kotlin port
// (canonical TS: src/lib/json-minify.ts; Go twin: cli/json-minify). The JVM
// stdlib has no JSON codec, so — like the Rust port — this is a hand-rolled
// RFC 8259 scanner: validate, copy tokens verbatim, drop only whitespace.
class JsonMinify private constructor(private val src: String) {
    private val out = StringBuilder()
    private var i = 0
    private fun peek(): Char = if (i < src.length) src[i] else Char.MIN_VALUE
    private fun take(): Char { val c = peek(); i++; return c } // '\0' at end-of-input
    private fun skipWs() { while (peek() in " \t\n\r") i++ }
    private fun digits(): Boolean { var any = false; while (peek() in '0'..'9') { i++; any = true }; return any }
    private fun string(): Boolean {
        out.append('"'); i++ // opening quote
        while (true) {
            val c = take()
            when {
                c == '"' -> { out.append(c); return true }
                c == '\\' -> {
                    val e = take()
                    out.append(e)
                    if (e == 'u') repeat(4) { val h = take(); if (h !in '0'..'9' && h !in 'a'..'f' && h !in 'A'..'F') return false; out.append(h) }
                    else if (e !in "\"\\/bfnrt") return false
                }
                c < ' ' -> return false // control char / EOF
                else -> out.append(c)
            }
        }
    }
    // Numbers are grammar-checked and copied verbatim — no float round-trip.
    private fun number(): Boolean {
        val start = i
        if (peek() == '-') i++
        if (peek() == '0') i++ // "01" is rejected by the caller
        else if (peek() in '1'..'9') { i++; while (peek() in '0'..'9') i++ }
        else return false // bare '-'
        if (peek() == '.') { i++; if (!digits()) return false }
        if (peek() == 'e' || peek() == 'E') { i++; if (peek() == '+' || peek() == '-') i++; if (!digits()) return false }
        out.append(src, start, i)
        return true;
    }
    private fun literal(word: String): Boolean {
        if (!src.startsWith(word, i)) return false
        out.append(word); i += word.length
        return true
    }
    private fun value(): Boolean {
        skipWs()
        val c = peek()
        if (c == '{' || c == '[') {
            val close = if (c == '{') '}' else ']'
            out.append(c); i++; skipWs()
            if (peek() == close) { out.append(close); i++; return true } // {} / []
            while (true) {
                if (close == '}') { skipWs(); if (peek() != '"' || !string()) return false; skipWs(); if (take() != ':') return false; out.append(':') }
                if (!value()) return false
                skipWs()
                val d = take()
                if (d == ',') { out.append(d); continue }
                if (d == close) { out.append(close); return true }
                return false
            }
        }
        if (c == '"') return string()
        if (c == 't' || c == 'f' || c == 'n') return literal(if (c == 't') "true" else if (c == 'f') "false" else "null")
        return (c == '-' || c in '0'..'9') && number()
    }
    companion object {
        // Compact JSON serialization of input, or null for invalid JSON.
        fun minify(input: String): String? {
            val p = JsonMinify(input)
            if (!p.value()) return null
            p.skipWs()
            return if (p.i == p.src.length) p.out.toString() else null // trailing garbage
        }
    }
}
fun main() {
    println(JsonMinify.minify("{\n  \"a\": 1,\n  \"b\": [\n    1,\n    2\n  ]\n}")) // {"a":1,"b":[1,2]}
    println(JsonMinify.minify("{invalid}")) // null — invalid JSON
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →