JSON Minify — Swift 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 Swift implementation — the same logic the interactive tool runs, in a shareable, citable form.
// json-minify — compact JSON to its smallest valid form. Swift port
// (canonical TS: src/lib/json-minify.ts; Go twin: cli/json-minify).
// Foundation's JSONSerialization re-escapes and loses key order, so — like
// the Rust port — this is a hand-rolled RFC 8259 scanner over UTF-8 bytes:
// validate, copy tokens verbatim, drop only whitespace. Invalid JSON -> nil.
struct JsonMinify {
private let src: [UInt8]
private var out: [UInt8] = []
private var i = 0
private func peek() -> UInt8 { i < src.count ? src[i] : 0 }
private mutating func take() -> UInt8 { let c = peek(); i += 1; return c } // 0 at end-of-input
private mutating func skipWs() { while peek() == 32 || peek() == 9 || peek() == 10 || peek() == 13 { i += 1 } }
private mutating func digits() -> Bool { var any = false; while peek() >= 0x30 && peek() <= 0x39 { i += 1; any = true }; return any }
private mutating func string() -> Bool {
out.append(src[i]); i += 1 // opening quote (0x22)
while true {
let c = take()
if c == 0x22 { out.append(c); return true } // closing quote
if c == 0x5C { // backslash
let e = take()
out.append(e)
if e == 0x75 { // 'u' — 4 hex digits
for _ in 0..<4 { let h = take(); if !"0123456789abcdefABCDEF".utf8.contains(h) { return false }; out.append(h) }
} else if !"\"\\/bfnrt".utf8.contains(e) { return false } // 0 is not in the set
} else if c < 0x20 { return false } // control byte / EOF
else { out.append(c) }
}
}
// Numbers are grammar-checked and copied verbatim — no float round-trip.
private mutating func number() -> Bool {
let start = i
if peek() == 0x2D { i += 1 } // '-'
if peek() == 0x30 { i += 1 } // '0' — "01" is rejected by the caller
else if peek() >= 0x31 && peek() <= 0x39 { i += 1; while peek() >= 0x30 && peek() <= 0x39 { i += 1 } }
else { return false } // bare '-'
if peek() == 0x2E { i += 1; if !digits() { return false } } // '.'
if peek() == 0x65 || peek() == 0x45 { i += 1; if peek() == 0x2B || peek() == 0x2D { i += 1 }; if !digits() { return false } } // e/E
out.append(contentsOf: src[start..<i])
return true
}
private mutating func literal(_ word: String) -> Bool {
let w = Array(word.utf8)
guard i <= src.count, src.count - i >= w.count, Array(src[i..<i + w.count]) == w else { return false }
out.append(contentsOf: w); i += w.count
return true
}
// Objects and arrays share one loop: ',' continues, the matching bracket
// closes; object elements are "key": value pairs.
private mutating func value() -> Bool {
skipWs()
let c = peek()
if c == 0x7B || c == 0x5B { // '{' or '['
let close: UInt8 = c == 0x7B ? 0x7D : 0x5D
out.append(c); i += 1; skipWs()
if peek() == close { out.append(close); i += 1; return true } // {} / []
while true {
if close == 0x7D { skipWs(); if peek() != 0x22 || !string() { return false }; skipWs(); if i >= src.count || src[i] != 0x3A { return false }; i += 1; out.append(0x3A) } // "key":
if !value() { return false }
skipWs()
let d = take()
if d == 0x2C { out.append(d); continue } // ','
if d == close { out.append(close); return true }
return false
}
}
if c == 0x22 { return string() }
if c == 0x74 || c == 0x66 || c == 0x6E { return literal(c == 0x74 ? "true" : c == 0x66 ? "false" : "null") }
return (c == 0x2D || (c >= 0x30 && c <= 0x39)) && number()
}
// Compact JSON serialization of input, or nil for invalid JSON.
static func minify(_ input: String) -> String? {
var p = JsonMinify(src: Array(input.utf8))
guard p.value() else { return nil }
p.skipWs()
guard p.i == p.src.count else { return nil } // trailing garbage fails
return String(decoding: p.out, as: UTF8.self)
}
}
print(JsonMinify.minify("{\n \"a\": 1,\n \"b\": [\n 1,\n 2\n ]\n}") ?? "(invalid)") // {"a":1,"b":[1,2]}
print(JsonMinify.minify("{invalid}") ?? "(nil — invalid JSON)") // invalid JSON -> nil
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 →