Skip to content

JSON Minify — Java 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 Java implementation — the same logic the interactive tool runs, in a shareable, citable form.

// json-minify — compact JSON to its smallest valid form. Java 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. Invalid ->
// null.
public final class JsonMinify {
    private final String src; private final StringBuilder out = new StringBuilder(); private int i;
    private JsonMinify(String src) { this.src = src; }
    /** Compact JSON serialization of input, or null for invalid JSON. */
    public static String minify(String input) {
        JsonMinify p = new JsonMinify(input);
        if (!p.value()) return null;
        p.skipWs();
        return p.i == p.src.length() ? p.out.toString() : null; // trailing garbage fails
    }
    private char peek() { return i < src.length() ? src.charAt(i) : '\0'; }
    private char take() { char c = peek(); i++; return c; } // '\0' at end-of-input
    private void skipWs() { while (" \t\n\r".indexOf(peek()) >= 0) i++; }
    private boolean digits() { boolean any = false; while (peek() >= '0' && peek() <= '9') { i++; any = true; } return any; }
    private boolean string() {
        out.append('"'); i++; // opening quote
        for (;;) {
            char c = take();
            if (c == '"') { out.append(c); return true; }
            if (c == '\\') {
                char e = take();
                out.append(e);
                if (e == 'u') { for (int k = 0; k < 4; k++) { char h = take(); if (Character.digit(h, 16) < 0) return false; out.append(h); } }
                else if ("\"\\/bfnrt".indexOf(e) < 0) return false; // '\0' is not in the set
            } else if (c < 0x20) return false; // control char / EOF
            else out.append(c);
        }
    }
    // Numbers are grammar-checked and copied verbatim — no float round-trip.
    private boolean number() {
        int start = i;
        if (peek() == '-') i++;
        if (peek() == '0') i++; // "01" is rejected by the caller
        else if (peek() >= '1' && peek() <= '9') { i++; digits(); }
        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 boolean literal(String word) {
        if (!src.startsWith(word, i)) return false;
        out.append(word); i += word.length();
        return true;
    }
    // Objects and arrays share one loop: ',' continues, the matching bracket
    // closes; object elements are "key": value pairs.
    private boolean value() {
        skipWs();
        char c = peek();
        if (c == '{' || c == '[') {
            char close = c == '{' ? '}' : ']';
            out.append(c); i++; skipWs();
            if (peek() == close) { out.append(close); i++; return true; } // {} / []
            for (;;) {
                if (close == '}') { skipWs(); if (peek() != '"' || !string()) return false; skipWs(); if (take() != ':') return false; out.append(':'); }
                if (!value()) return false;
                skipWs();
                char 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(c == 't' ? "true" : c == 'f' ? "false" : "null");
        return (c == '-' || (c >= '0' && c <= '9')) && number();
    }
    public static void main(String[] args) {
        System.out.println(minify("{\n  \"a\": 1,\n  \"b\": [\n    1,\n    2\n  ]\n}")); // {"a":1,"b":[1,2]}
        System.out.println(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 →