| name | clojure-babashka-json |
| description | babashka.json is a cross-platform JSON abstraction for Clojure/babashka. Use when working with JSON parsing, serialization, or writing portable code that runs on both JVM and babashka. |
babashka.json
A minimal abstraction over multiple JSON implementations, providing a unified API that works seamlessly in both JVM Clojure and babashka.
The library automatically selects the best available JSON implementation on your classpath without requiring conditional reader macros or platform-specific code.
Setup
deps.edn:
org.babashka/json {:mvn/version "0.1.7"}
Leiningen:
[org.babashka/json "0.1.7"]
See https://clojars.org/org.babashka/json for the latest version.
Quick Start
(require '[babashka.json :as json])
;; Parse JSON string to Clojure data
(json/read-str "{\"name\": \"Alice\", \"age\": 30}")
;; => {:name "Alice", :age 30}
;; Serialize Clojure data to JSON
(json/write-str {:name "Bob" :age 25})
;; => "{\"name\":\"Bob\",\"age\":25}"
;; Round-trip
(-> {:users [{:id 1} {:id 2}]}
json/write-str
json/read-str)
;; => {:users [{:id 1} {:id 2}]}
Core Functions
read-str - Parse JSON string
;; Basic parsing - keys become keywords by default
(json/read-str "{\"a\": 1, \"b\": 2}")
;; => {:a 1, :b 2}
;; Arrays
(json/read-str "[1, 2, 3]")
;; => [1 2 3]
;; Keep string keys
(json/read-str "{\"a\": 1}" {:key-fn str})
;; => {"a" 1}
;; Custom key transformation
(json/read-str "{\"user_id\": 123}" {:key-fn #(-> % keyword str/upper-case keyword)})
;; => {:USER_ID 123}
Options:
:key-fn- Function to transform JSON object keys. Defaults tokeyword.
write-str - Serialize to JSON
;; Maps
(json/write-str {:name "Alice" :active true})
;; => "{\"name\":\"Alice\",\"active\":true}"
;; Vectors
(json/write-str [1 2 3])
;; => "[1,2,3]"
;; Nested structures
(json/write-str {:users [{:id 1 :name "Alice"}
{:id 2 :name "Bob"}]})
;; => "{\"users\":[{\"id\":1,\"name\":\"Alice\"},{\"id\":2,\"name\":\"Bob\"}]}"
;; Keywords become strings
(json/write-str {:status :active})
;; => "{\"status\":\"active\"}"
read - Parse from reader
(require '[clojure.java.io :as io])
;; Read from file
(with-open [rdr (io/reader "data.json")]
(json/read (json/->json-reader rdr)))
;; Read from string reader
(let [rdr (json/->json-reader (java.io.StringReader. "{\"a\": 1}"))]
(json/read rdr))
;; => {:a 1}
;; With custom key function
(let [rdr (json/->json-reader (java.io.StringReader. "{\"a\": 1}")
{:key-fn str})]
(json/read rdr {:key-fn str}))
;; => {"a" 1}
get-provider - Check current implementation
(json/get-provider)
;; => cheshire/cheshire (in babashka)
;; => org.clojure/data.json (on JVM without other deps)
Provider Selection
On the JVM, babashka.json automatically uses the first available library in this order:
- cheshire/cheshire (babashka default)
- com.cnuernber/charred
- metosin/jsonista
- org.clojure/data.json (bundled fallback)
Force a specific provider via JVM property BEFORE loading the library:
;; In deps.edn :jvm-opts
:jvm-opts ["-Dbabashka.json.provider=com.cnuernber/charred"]
;; Or programmatically (must be before requiring babashka.json)
(System/setProperty "babashka.json.provider" "metosin/jsonista")
(require '[babashka.json :as json])
Valid provider values:
cheshire/cheshirecom.cnuernber/charredmetosin/jsonistaorg.clojure/data.json
Common Patterns
API Response Handling
(require '[babashka.json :as json])
(defn fetch-user [id]
(-> (http/get (str "https://api.example.com/users/" id))
:body
(json/read-str)))
;; Use the data
(let [user (fetch-user 123)]
(println "User:" (:name user)))
File I/O
(require '[clojure.java.io :as io]
'[babashka.json :as json])
;; Write JSON to file
(defn save-config [config path]
(spit path (json/write-str config)))
;; Read JSON from file
(defn load-config [path]
(json/read-str (slurp path)))
;; Streaming large files
(defn read-large-json [path]
(with-open [rdr (io/reader path)]
(json/read (json/->json-reader rdr))))
babashka Scripts
#!/usr/bin/env bb
(require '[babashka.json :as json])
;; Read from stdin
(let [data (json/read-str (slurp *in*))]
(println "Processing" (count data) "records"))
;; Write to stdout
(println (json/write-str {:status "ok" :timestamp (System/currentTimeMillis)}))
Portable JVM/babashka Code
Instead of this:
#?(:bb (cheshire.core/parse-string s keyword)
:clj (clojure.data.json/read-str s :key-fn keyword))
Write this:
(require '[babashka.json :as json])
(json/read-str s)
Works identically on both platforms.
Key Gotchas
Keywords vs Strings: By default, JSON object keys become keywords. Use
:key-fn strif you need string keys.Provider must be set early: The
babashka.json.providersystem property must be set BEFORE the library is loaded. Setting it after has no effect.Excluding the bundled dependency: If you don't want
org.clojure/data.jsonon your classpath:org.babashka/json {:mvn/version "0.1.7" :exclusions [org.clojure/data.json]}But ensure you have another JSON library available.
Minimal API surface: This library intentionally provides only the most common operations. For advanced features (pretty printing, custom encoders, streaming), use the underlying provider directly.
Different providers have different behavior: While the API is unified, edge cases (number precision, date handling) may differ between providers. Test your specific use case if switching providers.
Reader options must match: When using
->json-readerwith options, pass the same options toread:;; Correct (let [rdr (json/->json-reader input {:key-fn str})] (json/read rdr {:key-fn str})) ;; May not work as expected (let [rdr (json/->json-reader input {:key-fn str})] (json/read rdr)) ; Missing {:key-fn str}
When to Use This Library
Use babashka.json when:
- Writing portable code for both JVM Clojure and babashka
- Building babashka scripts that need JSON
- You want automatic provider selection based on classpath
- You only need basic JSON read/write operations
Don't use babashka.json when:
- You need advanced features (custom encoders, pretty printing, streaming)
- You're already locked into a specific JSON library with custom configuration
- You need fine-grained control over JSON parsing behavior
For advanced use cases, depend on your chosen provider directly (cheshire, jsonista, etc.) and use its full API.
References
- GitHub: https://github.com/babashka/json
- Clojars: https://clojars.org/org.babashka/json
- Babashka: https://github.com/babashka/babashka