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 →