Skip to content
Clojure JSON and JSON SMILE (binary json format) encoding/decoding
Find file
New pull request
Pull request Compare This branch is 1 commit ahead, 271 commits behind dakrone:master.
Fetching latest commit...
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


'Cheshire Puss,' she began, rather timidly, as she did not at all know whether it would like the name: however, it only grinned a little wider. 'Come, it's pleased so far,' thought Alice, and she went on. 'Would you tell me, please, which way I ought to go from here?'

'That depends a good deal on where you want to get to,' said the Cat.

'I don't much care where--' said Alice.

'Then it doesn't matter which way you go,' said the Cat.

'--so long as I get SOMEWHERE,' Alice added as an explanation.

'Oh, you're sure to do that,' said the Cat, 'if you only walk long enough.'

Cheshire is fast JSON encoding, based off of clj-json and clojure-json, with additional features like Date/UUID/Set/Symbol encoding and SMILE support.

Clojure code with docs

Continuous Integration status


clojure-json had really nice features (custom encoders), but was slow; clj-json had no features, but was fast. Cheshire encodes JSON fast, with the ability to use custom encoders.


[cheshire "2.0.3"]

;; Cheshire v2.0.3 uses Jackson 1.9.2

;; In your ns statement:
(ns myns
  (:use [cheshire.core]))


;; generate some json
(generate-string {:foo "bar" :baz 5})

;; write some json to a stream
(generate-stream {:foo "bar" :baz 5} ( "/tmp/foo"))

;; generate some SMILE
(generate-smile {:foo "bar" :baz 5})

;; generate some JSON with Dates
;; the Date will be encoded as a string using
;; the default date format: yyyy-MM-dd'T'HH:mm:ss'Z'
(generate-string {:foo "bar" :baz (Date. 0)})

;; generate some JSON with Dates with custom Date encoding
(generate-string {:baz (Date. 0)} "yyyy-MM-dd")


;; parse some json
(parse-string "{\"foo\":\"bar\"}")
;; => {"foo" "bar"}

;; parse some json and get keywords back
(parse-string "{\"foo\":\"bar\"}" true)
;; => {:foo "bar"}

;; parse some SMILE (keywords option also supported)
(parse-smile <your-byte-array>)

;; parse a stream (keywords option also supported)
(parse-stream ( "/tmp/foo"))

;; parse a stream lazily (keywords option also supported)
(parsed-seq ( "/tmp/foo"))

;; parse a SMILE stream lazily (keywords option also supported)
(parsed-smile-seq ( "/tmp/foo"))

Custom Encoders

Custom encoding is supported from 2.0.0 and up, however there still may be bugs, if you encounter a bug, please open a github issue.

;; Custom encoders allow you to swap out the api for the fast
;; encoder with one that is slightly slower, but allows custom
;; things to be encoded:
(ns myns
  (:use [cheshire.custom]))

;; First, add a custom encoder for a class:
(add-encoder java.awt.Color
             (fn [c jsonGenerator]
               (.writeString jsonGenerator (str c))))

;; There are also helpers for common encoding actions:
(add-encoder encode-str)

;; List of common encoders that can be used: (see custom.clj)
;; encode-nil
;; encode-number
;; encode-seq
;; encode-date
;; encode-bool
;; encode-named
;; encode-map
;; encode-symbol
;; encode-ratio

;; Then you can use encode from the custom namespace as normal
(encode (java.awt.Color. 1 2 3))
;; => "java.awt.Color[r=1,g=2,b=3]"

;; Custom encoders can also be removed:
(remove-encoder java.awt.Color)

;; Decoding remains the same, you are responsible for doing custom decoding.

Custom (slower) and Core (faster) encoding can be mixed and matched by requiring both namespaces and using the custom one only when you need to encode custom classes. The API methods for cheshire.core and cheshire.custom are exactly the same (except for add-encoder and remove-encoder in the custom namespace).

There are also a few aliases for commonly used functions:

encode -> generate-string
encode-stream -> generate-stream
encode-smile -> generate-smile
decode -> parse-string
decode-stream -> parse-stream
decode-smile -> parse-smile


Cheshire supports encoding standard clojure datastructures, with a few additions.

Cheshire encoding supports:

Clojure data structures

  • strings
  • lists
  • vectors
  • sets
  • maps
  • symbols
  • booleans
  • keywords (qualified and unqualified)
  • numbers (Integer, Long, BigInteger, BigInt, Double, Float, Ratio, primatives)

Java classes

  • Date
  • UUID
  • java.sql.Timestamp

Custom class encoding while still being fast

Also supports


Clojure version:  1.2.1
Num roundtrips:   100000

Trial:  1
clj-json                               2.16
clj-json w/ keywords                   2.43
clj-serializer                         2.13
cheshire                               2.19
cheshire-smile                         2.20
cheshire w/ keywords                   2.12
clojure printer/reader                 7.16
clojure printer/reader w/ print-dup    12.29
clojure-json                           20.55 (0.1.2)              4.67

Trial:  2
clj-json                               1.23
clj-json w/ keywords                   2.17
clj-serializer                         1.58
cheshire                               1.49
cheshire-smile                         1.49
cheshire w/ keywords                   1.99
clojure printer/reader                 5.97
clojure printer/reader w/ print-dup    11.17
clojure-json                           20.42 (0.1.2)              4.12

Benchmarks for custom encoding coming soon.

Future Ideas/TODOs

  • move away from using Java entirely, use Protocols for the custom encoder (see custom.clj)
  • allow custom encoders (see custom.clj)
  • figure out a way to encode namespace-qualified keywords
  • look into overriding the default encoding handlers with custom handlers
  • better handling when java numbers overflow ECMAScript's numbers (-2^31 to (2^31 - 1))
  • handle encoding java.sql.Timestamp the same as java.util.Date
  • make it as fast as possible


Release under the MIT license. See LICENSE for the full license.


Thanks go to Mark McGranaghan for allowing me to look at the clj-json code to get started on this and Jim Duey for the name. :)

Something went wrong with that request. Please try again.