jsonissa / jsonista / jsoniin, jsonilla / jsonilta / jsonille
Clojure library for fast JSON encoding and decoding.
- Explicit configuration
- Uses jackson-databind
- Mostly written in Java for speed
- API docs
- FAQ
Faster than data.json or Cheshire while still having the necessary features for web development. Designed for use with Muuntaja.
Blogged:
Requires Java1.8+
(require '[jsonista.core :as j])
(j/write-value-as-string {"hello" 1})
;; => "{\"hello\":1}"
(j/read-value *1)
;; => {"hello" 1}
Using explicit ObjectMapper:
(-> {:dog {:name "Teppo"}}
(j/write-value-as-bytes j/default-object-mapper)
(j/read-value j/default-object-mapper))
;; => {"dog" {"name" "Teppo"}}
Using keyword keys:
(-> {:dog {:name "Teppo"}}
(j/write-value-as-bytes j/keyword-keys-object-mapper)
(j/read-value j/keyword-keys-object-mapper))
;; => {:dog {:name "Teppo"}}
Changing how map keys are encoded & decoded:
(defn reverse-string [s] (apply str (reverse s)))
(def mapper
(j/object-mapper
{:encode-key-fn (comp reverse-string name)
:decode-key-fn (comp keyword reverse-string)}))
(-> {:kikka "kukka"}
(doto prn)
(j/write-value-as-string mapper)
(doto prn)
(j/read-value mapper)
(prn))
; {:kikka "kukka"}
; "{\"akkik\":\"kukka\"}"
; {:kikka "kukka"}
Reading & writing directly into a file:
(def file (java.io.File. "hello.json"))
(j/write-value file {"hello" "world"})
(slurp file)
;; => "{\"hello\":\"world\"}"
(j/read-value file)
;; => {"hello" "world"}
Adding support for joda-time Classes, used by clj-time.
;; [com.fasterxml.jackson.datatype/jackson-datatype-joda "2.9.5"]
(import '[com.fasterxml.jackson.datatype.joda JodaModule])
(import '[org.joda.time LocalDate])
(def mapper
(j/object-mapper
{:modules [(JodaModule.)]}))
(j/write-value-as-string (LocalDate. 0) mapper)
; "\"1970-01-01\""
Adding support for lossless encoding data using tagged values. This includes both reading and writing support.
(def mapper
(j/object-mapper
{:encode-key-fn true
:decode-key-fn true
:modules [(jt/module
{:handlers {Keyword {:tag "!kw"
:encode jt/encode-keyword
:decode keyword}
PersistentHashSet {:tag "!set"
:encode jt/encode-collection
:decode set}}})]}))
(-> {:system/status #{:status/good}}
(j/write-value-as-string mapper)
(doto prn)
(j/read-value mapper))
; prints "{\"system/status\":[\"!set\",[[\"!kw\",\"status/good\"]]]}"
; => {:system/status #{:status/good}}
In simple perf tests, tagged JSON is much faster than EDN or Transit.
- All standard encoders and decoders are written in Java
- Protocol dispatch with
read-value
&write-value
- Jackson
ObjectMapper
is used directly - Small functions to support JVM Inlining
Measured using lein-jmh, see perf-tests for details.
➜ jsonista git:(master) ✗ lein jmh '{:file "benchmarks.edn", :type :quick, :format :table}'
{:% 100.0 :eta "00:00:00"}
:benchmark :name :mode :samples :score :score-error :params
----------------------------- ------- ----------- -------- ------------------ ------------ --------------
jsonista.jmh/encode-data-json :encode :throughput 5 2011809.137 ops/s 12600.809 {:size "10b"}
jsonista.jmh/encode-data-json :encode :throughput 5 382677.707 ops/s 2861.142 {:size "100b"}
jsonista.jmh/encode-data-json :encode :throughput 5 66403.631 ops/s 597.436 {:size "1k"}
jsonista.jmh/encode-data-json :encode :throughput 5 5480.185 ops/s 58.379 {:size "10k"}
jsonista.jmh/encode-data-json :encode :throughput 5 576.691 ops/s 15.682 {:size "100k"}
jsonista.jmh/encode-cheshire :encode :throughput 5 996875.314 ops/s 5688.227 {:size "10b"}
jsonista.jmh/encode-cheshire :encode :throughput 5 482130.613 ops/s 2685.181 {:size "100b"}
jsonista.jmh/encode-cheshire :encode :throughput 5 128936.005 ops/s 879.709 {:size "1k"}
jsonista.jmh/encode-cheshire :encode :throughput 5 12209.066 ops/s 94.285 {:size "10k"}
jsonista.jmh/encode-cheshire :encode :throughput 5 1258.157 ops/s 12.340 {:size "100k"}
jsonista.jmh/encode-jsonista :encode :throughput 5 6356105.348 ops/s 85360.100 {:size "10b"}
jsonista.jmh/encode-jsonista :encode :throughput 5 2010379.039 ops/s 67648.165 {:size "100b"}
jsonista.jmh/encode-jsonista :encode :throughput 5 409264.663 ops/s 3704.992 {:size "1k"}
jsonista.jmh/encode-jsonista :encode :throughput 5 34527.245 ops/s 251.065 {:size "10k"}
jsonista.jmh/encode-jsonista :encode :throughput 5 2934.595 ops/s 15.858 {:size "100k"}
jsonista.jmh/encode-jackson :encode :throughput 5 6275467.563 ops/s 123578.482 {:size "10b"}
jsonista.jmh/encode-jackson :encode :throughput 5 2092035.098 ops/s 11417.613 {:size "100b"}
jsonista.jmh/encode-jackson :encode :throughput 5 408380.251 ops/s 10912.350 {:size "1k"}
jsonista.jmh/encode-jackson :encode :throughput 5 31992.554 ops/s 230.781 {:size "10k"}
jsonista.jmh/encode-jackson :encode :throughput 5 2887.485 ops/s 12.491 {:size "100k"}
jsonista.jmh/decode-data-json :decode :throughput 5 2257552.949 ops/s 23890.443 {:size "10b"}
jsonista.jmh/decode-data-json :decode :throughput 5 498261.935 ops/s 2348.572 {:size "100b"}
jsonista.jmh/decode-data-json :decode :throughput 5 85191.855 ops/s 321.961 {:size "1k"}
jsonista.jmh/decode-data-json :decode :throughput 5 7763.264 ops/s 250.502 {:size "10k"}
jsonista.jmh/decode-data-json :decode :throughput 5 771.691 ops/s 6.559 {:size "100k"}
jsonista.jmh/decode-cheshire :decode :throughput 5 1099821.870 ops/s 14796.659 {:size "10b"}
jsonista.jmh/decode-cheshire :decode :throughput 5 544013.773 ops/s 4122.539 {:size "100b"}
jsonista.jmh/decode-cheshire :decode :throughput 5 109517.975 ops/s 911.623 {:size "1k"}
jsonista.jmh/decode-cheshire :decode :throughput 5 10017.553 ops/s 50.871 {:size "10k"}
jsonista.jmh/decode-cheshire :decode :throughput 5 1014.003 ops/s 18.609 {:size "100k"}
jsonista.jmh/decode-jsonista :decode :throughput 5 3476196.425 ops/s 21535.641 {:size "10b"}
jsonista.jmh/decode-jsonista :decode :throughput 5 792773.466 ops/s 8209.591 {:size "100b"}
jsonista.jmh/decode-jsonista :decode :throughput 5 160180.797 ops/s 554.940 {:size "1k"}
jsonista.jmh/decode-jsonista :decode :throughput 5 14151.302 ops/s 107.906 {:size "10k"}
jsonista.jmh/decode-jsonista :decode :throughput 5 1508.829 ops/s 5.855 {:size "100k"}
jsonista.jmh/decode-jackson :decode :throughput 5 5145394.434 ops/s 84237.662 {:size "10b"}
jsonista.jmh/decode-jackson :decode :throughput 5 1339393.911 ops/s 6660.176 {:size "100b"}
jsonista.jmh/decode-jackson :decode :throughput 5 274465.912 ops/s 1589.614 {:size "1k"}
jsonista.jmh/decode-jackson :decode :throughput 5 29607.044 ops/s 183.068 {:size "10k"}
jsonista.jmh/decode-jackson :decode :throughput 5 2539.491 ops/s 17.753 {:size "100k"}
- Update
CHANGELOG.md
and increment the version number inproject.clj
- Commit and push to Github
- Create a Github release here
- Use the version number of the release for the tag name
- The Github Actions release workflow should fire and deploy a release to clojars
Copyright © 2016-2021 Metosin Oy.
Distributed under the Eclipse Public License 2.0.