[Git][clojure-team/cheshire-clojure][upstream] New upstream version 6.2.1

Jérôme Charaoui (@lavamind) gitlab at salsa.debian.org
Thu Nov 5 19:06:40 GMT 2026



Jérôme Charaoui pushed to branch upstream at Debian Clojure Maintainers / cheshire-clojure


Commits:
6ca48b0d by Jérôme Charaoui at 2026-11-04T19:18:12-05:00
New upstream version 6.2.1
- - - - -


23 changed files:

- + .clj-kondo/config.edn
- + .github/workflows/nvd_scan.yml
- + .github/workflows/test.yml
- .gitignore
- − .travis.yml
- ChangeLog.md
- README.md
- + cheshire_puss.png
- + nvd-helper/deps.edn
- + nvd-helper/nvd-clojure.edn
- + nvd-helper/suppressions.xml
- project.clj
- src/cheshire/core.clj
- src/cheshire/custom.clj
- src/cheshire/exact.clj
- src/cheshire/experimental.clj
- src/cheshire/factory.clj
- src/cheshire/generate.clj
- src/cheshire/generate_seq.clj
- src/cheshire/parse.clj
- test/cheshire/test/core.clj
- test/cheshire/test/custom.clj
- test/cheshire/test/generative.clj


Changes:

=====================================
.clj-kondo/config.edn
=====================================
@@ -0,0 +1 @@
+{:exclude-files "test/cheshire/test/generative.clj"}


=====================================
.github/workflows/nvd_scan.yml
=====================================
@@ -0,0 +1,82 @@
+name: Vulnerability Scan
+
+on:
+  schedule:
+    # daily
+    - cron: "5 0 * * *"
+  push:
+    branches:
+    - master
+
+jobs:
+  nvd-scan:
+    environment: nvd
+    runs-on: ubuntu-latest
+    steps:
+    - name: Checkout
+      uses: actions/checkout at v4
+
+    - name: Setup Java
+      uses: actions/setup-java at v4
+      with:
+        distribution: 'temurin'
+        java-version: 21
+
+    - name: Install Clojure Tools
+      uses: DeLaGuardo/setup-clojure at 13.2
+      with:
+        cli: 'latest'
+        lein: 'latest'
+
+    - name: Generate Cache Key File
+      run: |
+        # We are using RELEASE for deps, grab current versions for CI cache key
+        mkdir -p target
+        VERSION_NVD_CLOJURE=$(curl -s --fail https://clojars.org/api/artifacts/nvd-clojure/nvd-clojure | jq -r '.recent_versions[0].version')
+        VERSION_DEPENDENCY_CHECK=$(curl -s --fail 'https://search.maven.org/solrsearch/select?q=g:org.owasp+AND+a:dependency-check-core&core=gav&rows=1&wt=json' | jq '.response.docs[0].v')
+        echo "nvd-clojure=${VERSION_NVD_CLOJURE}" > target/ci-versions.txt
+        echo "dependency-check=${VERSION_DEPENDENCY_CHECK}" >> target/ci-versions.txt
+        cat target/ci-versions.txt
+      working-directory: nvd-helper
+
+    - name: Restore NVD DB & Clojure Deps Cache
+      # nvd caches its db under ~/.m2/repository/org/owasp so that it can
+      # conveniently be cached with deps
+      uses: actions/cache/restore at v4
+      with:
+        path: |
+          ~/.m2/repository
+          ~/.deps.clj
+          ~/.gitlibs
+        key: |
+          nvd-${{ hashFiles('nvd-helper/target/ci-versions.txt') }}
+        restore-keys: |
+          nvd-
+
+    - name: Tools Versions
+      run: |
+        echo "java -version"
+        java -version
+        echo "lein --version"
+        lein --version
+        echo "clojure --version"
+        clojure --version
+
+    - name: Run NVD Scanner
+      env:
+        NVD_API_TOKEN: ${{ secrets.NVD_API_TOKEN }}
+      run: clojure -J-Dclojure.main.report=stderr -J-Danalyzer.ossindex.enabled=false -M -m nvd.task.check "nvd-clojure.edn" "$(cd ..; lein classpath)"
+      working-directory: nvd-helper
+
+    - name: Save NVD DB & Clojure Deps Cache
+      if: always() # always cache regardless of outcome of nvd scan
+      uses: actions/cache/save at v4
+      with:
+        path: |
+          ~/.m2/repository
+          ~/.deps.clj
+          ~/.gitlibs
+        # we tack on github.run_id to uniquely identify the cache
+        # the next cache restore will find the best (and most current) match
+        key: |
+          nvd-${{ hashFiles('nvd-helper/target/ci-versions.txt') }}-${{ github.run_id }}


=====================================
.github/workflows/test.yml
=====================================
@@ -0,0 +1,105 @@
+name: Test
+
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+
+jobs:
+  lint:
+    runs-on: ubuntu-latest
+
+    steps:
+    - name: Checkout
+      uses: actions/checkout at v4
+
+    - name: Clojure deps cache
+      uses: actions/cache at v4
+      with:
+        path: |
+          ~/.m2/repository
+        key: ${{ runner.os }}-cljdeps-${{ hashFiles('project.clj') }}
+        restore-keys: ${{ runner.os }}-cljdeps-
+
+    - name: Setup Java
+      uses: actions/setup-java at v4
+      with:
+        distribution: 'temurin'
+        # We also lint with eastwood, using latest jdk release can help find
+        # JDK deprecations
+        java-version: 24
+
+    - name: Install Clojure Tools
+      uses: DeLaGuardo/setup-clojure at 13.2
+      with:
+        lein: 'latest'
+
+    - name: Download deps
+      run: lein all deps
+
+    - name: Tools Versions
+      run: |
+        echo "java -version"
+        java -version
+        echo "lein --version"
+        lein --version
+
+    - name: Lint with eastwood
+      run: lein eastwood
+
+    - name: Lint with clj-kondo
+      run: lein clj-kondo-lint
+
+  test:
+    runs-on: ${{ matrix.os }}-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ ubuntu, windows ]
+        java-version: [ '8', '11', '17', '21', '24' ]
+
+    defaults:
+      run:
+        # Windows lein.ps1 script is problematic, force lein.bat by using cmd shell
+        shell: ${{ matrix.os == 'windows' && 'cmd' || 'bash' }}
+
+    name: test ${{matrix.os}} jdk${{matrix.java-version}}
+
+    steps:
+    - name: Checkout
+      uses: actions/checkout at v4
+
+    - name: Clojure deps cache
+      uses: actions/cache at v4
+      with:
+        path: |
+          ~/.m2/repository
+        key: ${{ runner.os }}-cljdeps-${{ hashFiles('project.clj') }}
+        restore-keys: ${{ runner.os }}-cljdeps-
+
+    - name: Setup Java
+      uses: actions/setup-java at v4
+      with:
+        distribution: 'temurin'
+        java-version: ${{ matrix.java-version }}
+
+    - name: Install Clojure Tools
+      uses: DeLaGuardo/setup-clojure at 13.2
+      with:
+        lein: 'latest'
+
+    - name: Download deps
+      run: lein all deps
+
+    - name: Tools Versions
+      run: |
+        echo "java -version"
+        java -version
+        echo "lein --version"
+        lein --version
+
+    - name: Run Tests
+      run: lein all test :all


=====================================
.gitignore
=====================================
@@ -4,7 +4,7 @@ coref
 classes/*
 .lein-failures
 .lein-deps-sum
-target/*
+target
 pom.xml*
 doc*
 .lein*
@@ -12,3 +12,7 @@ doc*
 .idea
 *.iml
 .DS_Store
+.lsp
+.eastwood
+.cache
+.cpcache


=====================================
.travis.yml deleted
=====================================
@@ -1,11 +0,0 @@
-language: clojure
-lein: lein
-script: lein all test :all
-branches:
-  only:
-    - master
-jdk:
-  - openjdk8
-  - openjdk9
-  - openjdk10
-  - openjdk11


=====================================
ChangeLog.md
=====================================
@@ -1,105 +1,675 @@
-## Changes between Cheshire 5.8.1 and 5.9.0
+<!--
+The changelog is currently manually updated
+
+Changes should always be included when potentially interesting to users.
+
+Each change should include:
+- if possible/practical/meaningful, link to issue (else link to PR else link to commit)
+- short description of change
+- link to github profile of author of change
+
+Place any breaking changes under a "BREAKING changes" list item
+-->
+
+# v6.2.1 - 2026-11-02
+
+* Update Jackson dependencies to v2.21.8
+  [#255](https://github.com/dakrone/cheshire/pull/255)
+  ([@ray1729](https://github.com/ray1729))
+
+[commit log](https://github.com/dakrone/cheshire/compare/6.2.0...6.2.1)
+
+# v6.2.0 - 2026-03-19
+
+* Add support for JsonReadFeature `ALLOW_TRAILING_COMMA`
+  [#245](https://github.com/dakrone/cheshire/pull/245)
+  ([@esnyder](https://github.com/esnyder))
+* Update Jackson dependencies to v2.21.1
+  [#250](https://github.com/dakrone/cheshire/pull/250)
+  ([@dbasedow0000](https://github.com/dbasedow0000))
+
+[commit log](https://github.com/dakrone/cheshire/compare/6.1.0...6.2.0)
+
+# v6.1.0 - 2025-09-01
+
+* Add encoding for `java.time.Instant`
+  [#241](https://github.com/dakrone/cheshire/pull/241)
+  ([@mthl](https://github.com/mthl))
+* Add encoding for `java.util.concurrent.atomic.AtomicInteger`
+  [#243](https://github.com/dakrone/cheshire/pull/243)
+  ([@mthl](https://github.com/mthl))
+* Add encoding for `java.util.concurrent.atomic.AtomicLong`
+  [#243](https://github.com/dakrone/cheshire/pull/243)
+  ([@mthl](https://github.com/mthl))
+* Update Jackson dependencies to v2.20.0
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/6.0.0...6.1.0)
+
+# v6.0.0 - 2025-04-15
+
+* **BREAKING** changes
+  * [#217](https://github.com/dakrone/cheshire/issues/217):
+	Windows only: pretty printing now consistently uses JVM's OS default of `\r\n` for `:line-break`
+	([@lread](https://github.com/lread))
+* Bump minimum JDK version from v7 to v8
+  ([@lread](https://github.com/lread))
+* Bump Jackson to v2.18.3
+  ([@lread](https://github.com/lread))
+* [#209](https://github.com/dakrone/cheshire/pull/209):
+  Fix type hints on `generate-stream`
+  ([@souenzzo](https://github.com/souenzzo)])
+* [#210](https://github.com/dakrone/cheshire/issues/210):
+  Expose new Jackson processing limits via factory options
+  ([@lread](https://github.com/lread))
+* [#215](https://github.com/dakrone/cheshire/issues/215):
+  Add `:escape-non-ascii` to factory options
+  ([@lread](https://github.com/lread))
+* Internal maintenance:
+  * [#212](https://github.com/dakrone/cheshire/issues/212):
+	Migrate away from usages of deprecated Jackson
+	([@lread](https://github.com/lread))
+* Quality
+  * [#114](https://github.com/dakrone/cheshire/issues/114):
+	Freshen changelog and add missing history
+	([@lread](https://github.com/lread))
+  * [#214](https://github.com/dakrone/cheshire/issues/214):
+	Add CI on GitHub Actions and with test coverage on Linux and Windows
+	([@lread](https://github.com/lread))
+  * [#222](https://github.com/dakrone/cheshire/issues/222):
+	Add linting
+	([@lread](https://github.com/lread))
+  * [#226](https://github.com/dakrone/cheshire/issues/226):
+	Add vulnerability scanning for cheshire dependencies
+	([@lread](https://github.com/lread))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.13.0...6.0.0)
+
+# v5.13.0 - 2024-04-01
+
+* Bump Jackson to v2.17.0
+  ([@antonmos](https://github.com/antonmos))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.12.0...5.13.0)
+
+# v5.12.0 - 2023-09-19
+
+* Bump Jackson to v2.15.2
+  ([@jakepearson](https://github.com/jakepearson))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.11.0...5.12.0)
+
+# v5.11.0 - 2022-05-26
+
+* Bump Jackson to v2.13.3
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.10.2...5.11.0)
+
+# v5.10.2 - 2022-01-24
+
+* [ab52d71](https://github.com/dakrone/cheshire/commit/ab52d71):
+  Add data reader `#cheshire/json` tag to generate JSON strings
+  ([@mrroman](https://github.com/mrroman))
+* [#187](https://github.com/dakrone/cheshire/pull/187):
+  Exclude jackson-data-bind dependency, cheshire doesn't use and it has triggered many CVEs
+  ([@technomancy](https://github.com/technomancy))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.10.1...5.10.2)
+
+# v5.10.1 - 2021-07-13
+
+* Bump Jackson to v2.12.4
+  ([@dakrone](https://github.com/dakrone))
+* [#170](https://github.com/dakrone/cheshire/pull/170):
+  Add `:strict-duplicate-detection` to factory options
+  ([@sjamaan](https://github.com/sjamaan))
+* [7040a4a](https://github.com/dakrone/cheshire/commit/7040a4a):
+  Optimization: replace internal usage of `doseq` with `reduce`
+  ([@nilern](https://github.com/nilern))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.10.0...5.10.1)
+
+# v5.10.0 - 2020-02-04
+
+* Bump Jackson to v2.10.2
+  ([@willcohen](https://github.com/willcohen))
+* [#150](https://github.com/dakrone/cheshire/pull/150):
+  Bump tigris to v0.1.2
+  ([@aiba](https://github.com/aiba))
+* [9d69b18](https://github.com/dakrone/cheshire/commit/9d69b18):
+  Fix misplaced docstring (found with clj-kondo)
+  ([@borkdude](https://github.com/borkdude))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.9.0...5.10.0)
+
+# v5.9.0 - 2019-08-05
+
+* Bump Jackson to v2.9.9
+  ([@kumarshantanu](https://github.com/kumarshantanu))
+* [b980d98](https://github.com/dakrone/cheshire/commit/b980d98):
+  Add `parse-stream-strict` to parse streams strictly rather than lazily
+  ([@nilern](https://github.com/nilern))
+* [#141](https://github.com/dakrone/cheshire/pull/141):
+  Chunk size for lazy seqs is now configurable
+  ([@johnswanson](https://github.com/johnswanson) & ([@cayennes](https://github.com/cayennes)))
+* [fe453ea](https://github.com/dakrone/cheshire/commit/fe453ea):
+  Fix misplaced docstring (found with clj-kondo)
+  ([@borkdude](https://github.com/borkdude))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.8.1...5.9.0)
+
+# v5.8.1 - 2018-09-21
+
+* Bump Jackson to v2.9.6
+  ([@ikitommi](https://github.com/ikitommi))
+* [4ceaf16](https://github.com/dakrone/cheshire/commit/4ceaf16):
+  Add `:quote-field-names` factory option to control quoting field names in encoding
+  ([@crazymerlyn](https://github.com/crazymerlyn))
+* [#106](https://github.com/dakrone/cheshire/issues/106):
+  Respect `:indent-objects?` `false` in pretty printer
+  ([@crazymerlyn](https://github.com/crazymerlyn))
+* [#128](https://github.com/dakrone/cheshire/issues/128):
+  Add dependency on tools.namespace for clojure 1.9 compatability
+  ([@dakrone](https://github.com/dakrone))
+* [#131](https://github.com/dakrone/cheshire/issues/131):
+  Fix type hint in `parse-string-strict`
+  ([@spieden](https://github.com/spieden))
 
-* Add `parse-stream-strict` to parse streams strictly rather than lazily
-* Bump Jackson dependencies to 2.9.9
-* Chunk size for lazy seqs is now configurable
+[commit log](https://github.com/dakrone/cheshire/compare/5.8.0...5.8.1)
 
-## Changes between Cheshire 5.8.0 and 5.8.1
+# v5.8.0 - 2017-08-15
 
-* Add `:quote-field-names` parameter to control quoting field names in encoding
+* Bump Jackson to v2.9.0
+  ([@brabster](https://github.com/brabster))
+* [#111](https://github.com/dakrone/cheshire/issues/112):
+  Fix type hints for un-imported classes
+  ([@dakrone](https://github.com/dakrone))
+* Add `cheshire.exact` namespace for exactly-once decoding
+  ([@lucacervello](https://github.com/lucacervello))
+* Add only valid json option when parsing json
+  ([@lucacervello](https://github.com/lucacervello))
 
-## Changes between Cheshire 5.7.2 and 5.8.0
+[commit log](https://github.com/dakrone/cheshire/compare/5.7.1...5.8.0)
 
-* Fix type hints for un-imported classes
-* Update Jackson dependencies to mitigate vulnerability https://github.com/FasterXML/jackson-databind/issues/1599
-* Correct spelling in documentation
-* Add `cheshire.exact` namespace for exactly-once decoding
-* Bump Jackson dependencies to 2.9.0
+# v5.7.1 - 2017-04-20
 
-## Changes between Cheshire 5.6.3 and 5.6.2
+* [#112](https://github.com/dakrone/cheshire/issues/112):
+  Remove `condp` usage in `generate` to avoid memory issues for lazy seqs
+  ([@senior](https://github.com/senior))
 
-* Fix float coercion when encoding
+[commit log](https://github.com/dakrone/cheshire/compare/5.7.0...5.7.1)
 
-## Changes between Cheshire 5.6.2 and 5.6.1
+# v5.7.0 - 2017-01-13
 
-* Fix type hints for newer clojure version
-* Bump Jackson dependencies
+* Bump Jackson to v2.8.6
+  ([@dakrone](https://github.com/dakrone))
+* [847077d](https://github.com/dakrone/cheshire/commit/847077d):
+  Allow non const booleans `decode` for `key-fn`
+  ([@bfabry](https://github.com/bfabry))
 
-## Changes between Cheshire 5.6.1 and 5.6.0
+[commit log](https://github.com/dakrone/cheshire/compare/5.6.3...5.7.0)
 
-* Fix javac target for 1.6 compatibility
+# v5.6.3 - 2016-06-27
 
-## Changes between Cheshire 5.6.0 and 5.5.0
+* [#97](https://github.com/dakrone/cheshire/issues/97):
+  Fix float coercion when encoding
+  ([@dakrone](https://github.com/dakrone))
 
-* Fixes for type hinting
-* Make :pretty option configurable to use custom pretty printer
+[commit log](https://github.com/dakrone/cheshire/compare/5.6.2...5.6.3)
 
-## Changes between Cheshire 5.5.0 and 5.5.0
+# v5.6.2 - 2016-06-20
 
-* Bump Jackson dependencies
+* Bump Jackson to v2.7.5
+  ([@dakrone](https://github.com/dakrone))
+* [e949e00](https://github.com/dakrone/cheshire/commit/e949e00)
+  Fix type hints for newer clojure version
+  ([@pjstadig](https://github.com/pjstadig))
 
-## Changes between Cheshire 5.4.0 and 5.3.2
+[commit log](https://github.com/dakrone/cheshire/compare/5.6.1...5.6.2)
 
-* Add CBOR encoding/decoding
-* Add docstrings for clojure-json aliases
-* Add default encoder for java.lang.Character
-* Add sequential write support
-* Bump dependencies
+# v5.6.1 - 2016-04-12
 
-## Changes between Cheshire 5.3.1 and 5.3.0
+* [0d90f44](https://github.com/dakrone/cheshire/commit/0d90f44):
+  Tell javac to generate Java 1.6 compatible class files
+  ([@Deraen](https://github.com/Deraen))
 
-* Fix string parsing for 1 and 2 arity methods
-* Bump Jackson to 2.3.1
+[commit log](https://github.com/dakrone/cheshire/compare/5.6.0...5.6.1)
 
-## Changes between Cheshire 5.3.0 and 5.2.0
+# v5.6.0 - 2016-04-10
 
-* Dependencies have been bumped
-* Parse streams strictly by default to avoid scoping issues
+* Bump Jackson to v2.7.3
+  ([@niwinz](https://github.com/niwinz))
+* [#96](https://github.com/dakrone/cheshire/pull/96)
+  Fixes for type hinting
+  ([@ahjones](https://github.com/ahjones))
+* [77f9813](https://github.com/dakrone/cheshire/commit/77f9813)
+  Support byte-array encoding/decoding
+  ([@blendmaster](https://github.com/blendmaster))
+* [#99](https://github.com/dakrone/cheshire/issues/99):
+  Make `:pretty` option configurable to use custom pretty printer
+  ([@prayerslayer](https://github.com/prayerslayer))
 
-## Changes between Cheshire 5.2.0 and 5.1.2
+[commit log](https://github.com/dakrone/cheshire/compare/5.5.0...5.6.0)
 
-* Bump tigris to 0.1.1 to use PushbackReader
-* Lazily decode top-level arrays (thanks ztellman)
+# v5.5.0 - 2015-05-28
 
-## Changes between Cheshire 5.1.2 and 5.1.1
+* Bump Jackson to v2.5.3
+  ([@laczoka](https://github.com/laczoka))
+* [7124611](https://github.com/dakrone/cheshire/commit/7124611):
+  Add docstrings for clojure-json aliases
+  ([@danielcompton](https://github.com/danielcompton))
+* [#72](https://github.com/dakrone/cheshire/issues/72)
+  Address Jackson deprecations
+  ([@dakrone](https://github.com/dakrone))
 
-* Add experimental namespace
-* Bump Jackson deps to 2.2.1
+[commit log](https://github.com/dakrone/cheshire/compare/5.4.0...5.5.0)
 
-## Changes between Cheshire 5.1.1 and 5.1.0
+# v5.4.0 - 2014-12-10
 
-* Remove all reflection (thanks amalloy)
-* Fixed custom encoder helpers (thanks lynaghk)
+* Bump Jackson to v2.4.4
+  ([@dakrone](https://github.com/dakrone))
+* [ffac717](https://github.com/dakrone/cheshire/commit/ffac717):
+  Add CBOR encoding/decoding
+  ([@dakrone](https://github.com/dakrone))
+* [#53](https://github.com/dakrone/cheshire/issues/53):
+  Add default encoder for `java.lang.Character`
+  ([@dakrone](https://github.com/dakrone))
+* [56662c2](https://github.com/dakrone/cheshire/commit/56662c2):
+  Add sequential write support
+  ([@kostafey](https://github.com/kostafey))
 
-## Changes between Cheshire 5.1.0 and 5.0.2
+[commit log](https://github.com/dakrone/cheshire/compare/5.3.1...5.4.0)
 
-* Allow custom keyword function for encoding (thanks goodwink)
+# v5.3.1 - 2014-01-10
 
-## Changes between Cheshire 5.0.2 and 5.0.1
+* Bump Jackson to v2.3.1
+  ([@dakrone](https://github.com/dakrone))
+* [#46](https://github.com/dakrone/cheshire/issues/46)
+& [#48](https://github.com/dakrone/cheshire/issues/48):
+  Fix string parsing for 1 and 2 arity methods
+  ([@maxnoel](https://github.com/maxnoel))
 
-* Bump Jackson dependency from 2.1.1 to 2.1.3
+[commit log](https://github.com/dakrone/cheshire/compare/5.3.0...5.3.1)
 
-* Add more type hinting (thanks to ztellman)
+# v5.3.0 - 2013-12-18
 
-## Changes between Cheshire 5.0.0 and 5.0.1
+* Bump Jackson to v2.3.0
+  ([@dakrone](https://github.com/dakrone))
+* [#48](https://github.com/dakrone/cheshire/issues/48):
+  Parse streams strictly by default to avoid scoping issues
+  ([@dakrone](https://github.com/dakrone))
 
-* Protocol custom encoders now take precedence over regular map
-  encoders.
+[commit log](https://github.com/dakrone/cheshire/compare/5.2.0...5.3.0)
 
-* Benchmarking is now a separate lein command, not a test selector.
+# v5.2.0 - 2013-05-22
+
+* Bump tigris to v0.1.1 to use `PushbackReader`
+  ([@dakrone](https://github.com/dakrone))
+* Performance tweaks
+  ([@ztellman](https://github.com/ztellman))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.1.2...5.2.0)
+
+# v5.1.2 - 2013-05-17
+
+* Bump Jackson to v2.2.1
+  ([@dakrone](https://github.com/dakrone))
+* [ce4ff056](https://github.com/dakrone/cheshire/commit/ce4ff056):
+  Add experimental namespace
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.1.1...5.1.2)
+
+# v5.1.1 - 2013-04-12
+
+* [e4cc3b3](https://github.com/dakrone/cheshire/commit/e4cc3b3):
+  Remove all reflection
+  ([@amalloy](https://github.com/amalloy))
+* [6d78a56](https://github.com/dakrone/cheshire/commit/6d78a56):
+  Fixed custom encoder helpers
+  ([@lynaghk](https://github.com/lynaghk))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.1.0...5.1.1)
+
+# v5.1.0 - 2013-04-04
 
-## Changes between Cheshire 5.0.0 and 4.0.x
+* Bump Jackson to v2.1.4
+  ([@dakrone](https://github.com/dakrone))
+* [c5f0be3](https://github.com/dakrone/cheshire/commit/c5f0be3):
+  Allow custom keyword function for encoding
+  ([@goodwink](https://github.com/goodwink))
 
-### Custom Encoders Changes
+[commit log](https://github.com/dakrone/cheshire/compare/5.0.2...5.1.0)
 
-Custom encoder functions were moved to the `cheshire.generate` namespace:
+# v5.0.2 - 2013-02-19
 
- * `cheshire.custom/add-encoder` is now `cheshire.generate/add-encoder`
- * `cheshire.custom/remove-encoder` is now `cheshire.generate/remove-encoder`
+* Bump Jackson to v2.1.3
+  ([@dakrone](https://github.com/dakrone))
+* [03aff88](https://github.com/dakrone/cheshire/commit/03aff88):
+  Add more type hinting
+  ([@ztellman](https://github.com/ztellman))
 
-In addition, `cheshire.custom/encode` and `cheshire.custom/decode` are no longer
+[commit log](https://github.com/dakrone/cheshire/compare/5.0.1...5.0.2)
+
+# v5.0.1 - 2012-12-04
+
+* [#32](https://github.com/dakrone/cheshire/issues/32):
+  Protocol custom encoders now take precedence over regular map encoders.
+  ([@dakrone](https://github.com/dakrone))
+* Benchmarking is now a separate lein command, not a test selector.
+  ([@dakrone](https://github.com/dakrone))
+* Performance tweaks
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/5.0.0...5.0.1)
+
+# v5.0.0 - 2012-09-20
+
+* [#32](https://github.com/dakrone/cheshire/issues/32):
+  Custom Encoders Changes
+  ([@dakrone](https://github.com/dakrone))
+  * Custom encoder functions were moved to the `cheshire.generate` namespace:
+	* `cheshire.custom/add-encoder` is now `cheshire.generate/add-encoder`
+	* `cheshire.custom/remove-encoder` is now `cheshire.generate/remove-encoder`
+  * In addition, `cheshire.custom/encode` and `cheshire.custom/decode` are no longer
 necessary. Use `cheshire.core/encode` and `cheshire.core/decode` instead and
 those functions will pick up custom encoders while still preserving the same
 level of efficiency.
+  * The `cheshire.custom` namespace is now deprecated
+* Bump Jackson to v2.1.1
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/4.0.4...5.0.0)
+
+# v4.0.4 - 2012-11-19
+
+* Bump Jackson to v2.1.0
+  ([@dakrone](https://github.com/dakrone))
+* [811ea45](https://github.com/dakrone/cheshire/commit/811ea45):
+  Add missing writer arg for custom `encode-stream` passthrough to `encode-stream*`
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/4.0.3...4.0.4)
+
+# v4.0.3 - 2012-09-22
+
+* Bump Jackson to v2.0.6
+  ([@dakrone](https://github.com/dakrone))
+* [e7c5088](https://github.com/dakrone/cheshire/commit/e7c5088):
+  Make clojure a dev dependency
+  ([@dakrone](https://github.com/dakrone))
+* [10062af](https://github.com/dakrone/cheshire/commit/10062af):
+  Encode empty sets to empty arrays for consistency with empty array encoding
+  ([@dlebrero](https://github.com/dlebrero))
+* [9b32e2e](https://github.com/dakrone/cheshire/commit/9b32e2e):
+  Fix custom encoding of namespaced keywords
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/4.0.2...4.0.3)
+
+# v4.0.2 - 2012-08-30
+
+* Bump Jackson to v2.0.5
+  ([@dakrone](https://github.com/dakrone))
+* [bacb3ac](https://github.com/dakrone/cheshire/commit/bacb3ac):
+  Add support for escaping non-ASCII chars when decoding
+  ([@dakrone](https://github.com/dakrone))
+* [52a700b](https://github.com/dakrone/cheshire/commit/52a700b):
+  Add support for custom munging of keys when decoding
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/4.0.1...4.0.2)
+
+# v4.0.1 - 2012-06-12
+
+* Bump Jackson to v2.0.4
+  ([@dakrone](https://github.com/dakrone))
+* [6087d7f](https://github.com/dakrone/cheshire/commit/6087d7f):
+  Add support for encoding `Byte` and `Short` to int
+  ([@dakrone](https://github.com/dakrone))
+* [d05acde](https://github.com/dakrone/cheshire/commit/d05acde):
+  Add support for encoding `clojure.lang.Associative` to json map
+  ([@warsus](https://github.com/warsus))
+* Performance tweaks
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/4.0.0...4.0.1)
+
+# v4.0.0 - 2012-04-13
+
+* [20ebaa8](https://github.com/dakrone/cheshire/commit/20ebaa8):
+  Add optional default pretty printer to json generator
+  ([@drewr](https://github.com/drewr))
+* Support encoding with custom date format
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/3.1.0...4.0.0)
+
+# v3.1.0 - 2012-03-30
+
+* Bump Jackson to v2.0.0
+  ([@dakrone](https://github.com/dakrone))
+* Performance tweaks
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/3.0.0...3.1.0)
+
+# v3.0.0 - 2012-03-09
+
+* [65ace30](https://github.com/dakrone/cheshire/commit/65ace30):
+  Add support for encoding `clojure.lang.PersitentQueue`
+  ([@dakrone](https://github.com/dakrone))
+* [89348a7](https://github.com/dakrone/cheshire/commit/89348a7):
+  Throw `JsonGenerationExcption` instead of `Exception` when encoding fails
+  ([@dakrone](https://github.com/dakrone))
+* [714bec2](https://github.com/dakrone/cheshire/commit/714bec2):
+  Custom encoding now falls back to core encoding by default
+  ([@dakrone](https://github.com/dakrone))
+* [263ed65](https://github.com/dakrone/cheshire/commit/263ed65):
+  Encode qualified keywords `{:document/name "My document"} -> {"document/name" : "My document"}`
+  ([@maxweber](https://github.com/maxweber))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.2.2...3.0.0)
+
+# v2.2.2 - 2012-03-06
+
+* [6e4df40](https://github.com/dakrone/cheshire/commit/6e4df40):
+  Generate symbols as strings, encoding non-resolvable symbol without throwing
+  ([@dakrone](https://github.com/dakrone))
+* [#19](https://github.com/dakrone/cheshire/issues/19):
+  Fix custom encoding for Longs
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.2.1...2.2.2)
+
+# v2.2.1 - 2012-03-05
+
+* Bump Jackson to v1.9.5
+  ([@dakrone](https://github.com/dakrone))
+* [d2a9ad8a](https://github.com/dakrone/cheshire/commit/d2a9ad8a):
+  Add support for `java.util.{Map,List,Set}`
+  ([@ndimiduk](https://github.com/ndimiduk))
+* Performance tweaks
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.2.0...2.2.1)
+
+# v2.2.0 - 2012-02-07
+
+* [#16](https://github.com/dakrone/cheshire/issues/16):
+  Allow parsing floats into BigDecimal to retain precision
+  ([@dakrone](https://github.com/dakrone))
+* Various performance tweaks
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.1.0...2.2.0)
+
+# v2.1.0 - 2012-01-27
+
+* Bump Jackson to v1.9.4
+  ([@dakrone](https://github.com/dakrone))
+* Introduce `*json-factory*`, `*smile-factory*`, `*cbor-factory*` as a way to specify options to Jackson
+  ([@dakrone](https://github.com/dakrone))
+* Address some reflection warnings
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.0.6...2.1.0)
+
+# v2.0.6 - 2012-01-12
+
+* [b96106e](https://github.com/dakrone/cheshire/commit/b96106e):
+  Encode ns-qualified symbols consistently
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.0.5...2.0.6)
+
+# v2.0.5 - 2012-01-11
+
+* [eaee529](https://github.com/dakrone/cheshire/commit/eaee529):
+  Encode symbols that are not resolvable as strings
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.0.4...2.0.5)
+
+# v2.0.4 - 2011-11-29
+
+* [434099d](https://github.com/dakrone/cheshire/commit/434099d):
+  Support custom array coercion when parsing
+  ([@sbtourist](https://github.com/sbtourist))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.0.3...2.0.4)
+
+# v2.0.3 - 2011-11-26
+
+* Bump Jackson to v1.9.2
+  ([@dakrone](https://github.com/dakrone))
+* Support encoding of `clojure.lang.Ratio`
+  ([@dakrone](https://github.com/dakrone))
+* [de849ce](https://github.com/dakrone/cheshire/commit/de849ce):
+  Support encoding of `BigDecimal`
+  ([@CmdrDats](https://github.com/CmdrDats))
+* Don't attempt to parse `nil` things
+  ([@dakrone](https://github.com/dakrone) and [@zk](https://github.com/zk))
+* [750ae7c](https://github.com/dakrone/cheshire/commit/750ae7c):
+  Improve error message when encoding fails
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.0.2...2.0.3)
+
+# v2.0.2 - 2011-09-16
+
+* [db755c4](https://github.com/dakrone/cheshire/commit/db755c4):
+  Support encoding of `BigInteger`
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.0.1...2.0.2)
+
+# v2.0.1 - 2011-08-30
+
+* Bump Jackson to v1.8.5
+  ([@dakrone](https://github.com/dakrone))
+* [#6](https://github.com/dakrone/cheshire/issues/6):
+  Support encoding of `java.sql.Timestamp`
+  ([@dakrone](https://github.com/dakrone))
+* [8c686c2](https://github.com/dakrone/cheshire/commit/8c686c2):
+  Write namespace when encoding qualified keywords
+  ([@dakrone](https://github.com/dakrone))
+* Quality
+  * Automated testing on Travis CI
+	([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/2.0.0...2.0.1)
+
+# v2.0.0 - 2011-08-02
+
+* Bump Jackson to v1.8.3
+  ([@dakrone](https://github.com/dakrone))
+* Introduce `cheshire.factory` namespace
+  ([@dakrone](https://github.com/dakrone))
+* Continue work on custom encoders
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/1.1.4...2.0.0)
+
+# v1.1.4 - 2011-06-28
+
+* Bump Jackson to v1.8.2
+  ([@dakrone](https://github.com/dakrone))
+* [85f195b](https://github.com/dakrone/cheshire/commit/85f195b):
+  Add experimental custom encoders
+  ([@dakrone](https://github.com/dakrone))
+* [13db92a](https://github.com/dakrone/cheshire/commit/13db92a):
+  Add convenience methods for adding/removing custom encoders
+  ([@zk](https://github.com/zk))
+
+[commit log](https://github.com/dakrone/cheshire/compare/1.1.3...1.1.4)
+
+# v1.1.3 - 2011-05-25
+
+* Bump Jackson to v1.8.1
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/da8c206a22afffa55d4023b38ba0f7e6d4d69bdd...1.1.3)
+
+# v1.1.2 - 2011-04-29
+
+* [da8c206](https://github.com/dakrone/cheshire/commit/da8c206):
+  Support clojure v1.3
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/1.1.1...da8c206a22afffa55d4023b38ba0f7e6d4d69bdd)
+
+# v1.1.1 - 2011-04-18
+
+* [9cdc44c](https://github.com/dakrone/cheshire/commit/9cdc44c):
+  Add cheshire puss to README :)
+  ([@dakrone](https://github.com/dakrone))
+* [344e984](https://github.com/dakrone/cheshire/commit/344e984):
+  Stop using java for parsing
+  ([@hiredman](https://github.com/hiredman))
+* Quality
+  * Add time tests, address reflection warnings, and turf unused code
+	([@hiredman](https://github.com/hiredman))
+
+[commit log](https://github.com/dakrone/cheshire/compare/1.1.0...1.1.1)
+
+# v1.1.0 - 2011-03-29
+
+First world-consumption release of cheshire!
+
+* [04b2ce4](https://github.com/dakrone/cheshire/commit/04b2ce4):
+  Add `Date` and `UUID` encoding
+  ([@dakrone](https://github.com/dakrone))
+* [1e21b7d](https://github.com/dakrone/cheshire/commit/1e21b7d):
+  Add stream handling (encode/decode)
+  ([@dakrone](https://github.com/dakrone))
+* [215038d](https://github.com/dakrone/cheshire/commit/215038d):
+  Add helpers for streams
+  ([@dakrone](https://github.com/dakrone))
+* Add docs and cleanup docstrings
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/fca4fbb871ba43b3a00db90d96dd3bc95aa00174...1.1.0)
+
+# v1.0.2 - 2011-03-25
+
+* [fca4fbb](https://github.com/dakrone/cheshire/commit/fca4fbb):
+  Support encoding `#{}` and clojure symbols
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/76186a84a68442919d4c7d79eafae9ab40e5b9a0...fca4fbb871ba43b3a00db90d96dd3bc95aa00174)
+
+# v1.0.1 - 2011-03-25
+
+* [76186a8](https://github.com/dakrone/cheshire/commit/76186a8):
+  Add helpers for people coming from `clojure-json`
+  ([@dakrone](https://github.com/dakrone))
+
+[commit log](https://github.com/dakrone/cheshire/compare/33a0e24d7b63fd091afae20666d03ac68c829411...76186a84a68442919d4c7d79eafae9ab40e5b9a0)
+
+# v1.0.0 - 2011-03-25
+
+First release of cheshire!
 
-GH issue: [#32](https://github.com/dakrone/cheshire/issues/32).
+[commit log](https://github.com/dakrone/cheshire/compare/74eb30ec1a2f94c044c6e46ea4454ec3ab0e2934...33a0e24d7b63fd091afae20666d03ac68c829411)


=====================================
README.md
=====================================
@@ -1,8 +1,8 @@
 # Cheshire
 
-<img src="https://dakrone.github.io/cheshire/cheshire_small.jpg"
-title=":)" align="left" padding="5px" />
-<small>
+<img src="cheshire_puss.png" title=":)" align="left" />
+<!-- use italics to distiguish quote from other text -->
+<i>
 '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
@@ -18,17 +18,18 @@ on. 'Would you tell me, please, which way I ought to go from here?'
 
 'Oh, you're sure to do that,' said the Cat, 'if you only walk long
 enough.'
-</small>
-<br clear=all /><br />
+</i>
+<br clear=all />
+
 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](http://dakrone.github.io/cheshire/)
-
-[![Clojars Project](https://img.shields.io/clojars/v/cheshire.svg)](https://clojars.org/cheshire)
-[![Continuous Integration status](https://secure.travis-ci.org/dakrone/cheshire.png)](http://travis-ci.org/dakrone/cheshire)
+- [![Docs](https://cljdoc.org/badge/cheshire/cheshire)](https://cljdoc.org/d/cheshire/cheshire)
+- [![Clojars Project](https://img.shields.io/clojars/v/cheshire.svg)](https://clojars.org/cheshire)
+- [![Continuous Integration Tests](https://github.com/dakrone/cheshire/actions/workflows/test.yml/badge.svg)](https://github.com/dakrone/cheshire/actions/workflows/test.yml)
+- [![Vulnerability Scan](https://github.com/dakrone/cheshire/actions/workflows/nvd_scan.yml/badge.svg)](https://github.com/dakrone/cheshire/actions/workflows/nvd_scan.yml)
+- Cheshire is a built-in library in the [Babashka](https://babashka.org/) project
 
 ## Why?
 
@@ -40,9 +41,9 @@ encoders.
 ## Usage
 
 ```clojure
-[cheshire "5.11.0"]
+[cheshire "6.2.1"]
 
-;; Cheshire v5.11.0 uses Jackson 2.13.3
+;; Cheshire v6.2.1 uses Jackson 2.21.8
 
 ;; In your ns statement:
 (ns my.ns
@@ -85,9 +86,12 @@ encoders.
 ;; generate JSON and munge keys with a custom function
 (generate-string {:foo "bar"} {:key-fn (fn [k] (.toUpperCase (name k)))})
 ;; => "{\"FOO\":\"bar\"}"
+
+;; generate JSON without escaping the characters (by writing it to a file)
+(spit "foo.json" (json/generate-string {:foo "bar"} {:pretty true}))
 ```
 
-In the event encoding fails, Cheshire will throw a JsonGenerationException.
+In the event encoding fails, Cheshire will throw a `JsonGenerationException`.
 
 #### Custom Pretty Printing Options
 
@@ -97,8 +101,8 @@ or `encode` methods:
 
 ```clojure
 (let [my-pretty-printer (create-pretty-printer
-                          (assoc default-pretty-print-options
-                                 :indent-arrays? true))]
+						  (assoc default-pretty-print-options
+								 :indent-arrays? true))]
   (generate-string {:foo [1 2 3]} {:pretty my-pretty-printer}))
 ```
 
@@ -143,10 +147,10 @@ function to specify what kind of types to return, like so:
 ```clojure
 ;; In this example a function that checks for a certain key
 (decode "{\"myarray\":[2,3,3,2],\"myset\":[1,2,2,1]}" true
-        (fn [field-name]
-          (if (= field-name "myset")
-            #{}
-            [])))
+		(fn [field-name]
+		  (if (= field-name "myset")
+			#{}
+			[])))
 ;; => {:myarray [2 3 3 2], :myset #{1 2}}
 ```
 The type must be "transient-able", so use either #{} or []
@@ -165,12 +169,12 @@ namespace change)
 ;; things to be encoded:
 (ns myns
   (:require [cheshire.core :refer :all]
-            [cheshire.generate :refer [add-encoder encode-str remove-encoder]]))
+			[cheshire.generate :refer [add-encoder encode-str remove-encoder]]))
 
 ;; First, add a custom encoder for a class:
 (add-encoder java.awt.Color
-             (fn [c jsonGenerator]
-               (.writeString jsonGenerator (str c))))
+			 (fn [c jsonGenerator]
+			   (.writeString jsonGenerator (str c))))
 
 ;; There are also helpers for common encoding actions:
 (add-encoder java.net.URL encode-str)
@@ -206,12 +210,12 @@ on what you would like to use.
 
 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
+	encode -> generate-string
+	encode-stream -> generate-stream
+	encode-smile -> generate-smile
+	decode -> parse-string
+	decode-stream -> parse-stream
+	decode-smile -> parse-smile
 
 ## Features
 Cheshire supports encoding standard clojure datastructures, with a few
@@ -258,7 +262,7 @@ to true:
 ```clojure
 (ns foo.bar
   (require [cheshire.core :as json]
-           [cheshire.parse :as parse]))
+		   [cheshire.parse :as parse]))
 
 (json/decode "111111111111111111111111111111111.111111111111111111111111111111111111")
 ;; => 1.1111111111111112E32 (a Double)
@@ -273,7 +277,7 @@ to true:
 
 ## Change Log
 
-[Change log](https://github.com/dakrone/cheshire/blob/master/ChangeLog.md) is available on GitHub.
+[Change log](/ChangeLog.md) is available on GitHub.
 
 ## Speed
 
@@ -297,10 +301,10 @@ nil
 user> (use 'clojure.java.io)
 nil
 user> (println (slurp (encode-large-field-in-map {:id "10"
-                                                  :things [1 2 3]
-                                                  :body "I'll be removed"}
-                                                 :body
-                                                 (input-stream (file "/tmp/foo")))))
+												  :things [1 2 3]
+												  :body "I'll be removed"}
+												 :body
+												 (input-stream (file "/tmp/foo")))))
 {"things":[1,2,3],"id":"10","body":"Hi. \"THIS\" is a string.\\yep.\n"}
 nil
 ```
@@ -312,26 +316,21 @@ once (it returns a stream). Check out the docstring for full usage.
 It's experimental, like the name says. Based on [Tigris](http://github.com/dakrone/tigris).
 
 ## Advanced customization for factories
-See
-[this](http://fasterxml.github.com/jackson-core/javadoc/2.10/com/fasterxml/jackson/core/JsonFactory.Feature.html)
-and
-[this](http://fasterxml.github.com/jackson-core/javadoc/2.10/com/fasterxml/jackson/core/JsonParser.Feature.html)
-for a list of features that can be customized if desired. A custom
-factory can be used like so:
+A custom factory can be used like so:
 
 ```clojure
 (ns myns
   (:require [cheshire.core :as core]
-            [cheshire.factory :as factory]))
+			[cheshire.factory :as factory]))
 
 (binding [factory/*json-factory* (factory/make-json-factory
-                                  {:allow-non-numeric-numbers true})]
-  (json/decode "{\"foo\":NaN}" true))))))
+								  {:allow-non-numeric-numbers true})]
+  (json/decode "{\"foo\":NaN}" true))
 ```
 
 See the `default-factory-options` map in
-[factory.clj](https://github.com/dakrone/cheshire/blob/master/src/cheshire/factory.clj)
-for a full list of configurable options. Smile factories can also be
+[factory.clj](/src/cheshire/factory.clj)
+for a full list of configurable options. Smile and CBOR factories can also be
 created, and factories work exactly the same with custom encoding.
 
 ## Future Ideas/TODOs


=====================================
cheshire_puss.png
=====================================
Binary files /dev/null and b/cheshire_puss.png differ


=====================================
nvd-helper/deps.edn
=====================================
@@ -0,0 +1,5 @@
+{:deps {org.clojure/clojure {:mvn/version "1.12.0"}
+        ;; it is generally considered bad practice to use RELEASE, but we always want the latest
+        ;; security tooling
+        nvd-clojure/nvd-clojure #_:clj-kondo/ignore {:mvn/version "RELEASE"}
+        org.owasp/dependency-check-core #_:clj-kondo/ignore {:mvn/version "RELEASE"}}}


=====================================
nvd-helper/nvd-clojure.edn
=====================================
@@ -0,0 +1,3 @@
+{:delete-config? false
+ :nvd {:nvd-api {:max-retry-count 30}}
+ :suppression-file "./suppressions.xml"}


=====================================
nvd-helper/suppressions.xml
=====================================
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
+  <!-- This is an automatically generated config file by nvd-clojure. -->
+  <!-- Feel free to tweak it, version-control it and remove any comment. -->
+  <!-- You can find suppression examples in https://jeremylong.github.io/DependencyCheck/general/suppression.html -->
+  <suppress>
+    <notes><![CDATA[
+    This CVE is described as: An issue in Clojure versions 1.20 to 1.12.0-alpha5 allows an attacker to cause a denial of service (DoS) via the clojure.core$partial$fn__5920 function.
+    False positive; cheshire does not depend on a specific version of Clojure.
+    ]]></notes>
+    <cve>CVE-2024-22871</cve>
+  </suppress>
+</suppressions>


=====================================
project.clj
=====================================
@@ -1,23 +1,24 @@
-(defproject cheshire "5.11.0"
+(defproject cheshire "6.2.1"
   :description "JSON and JSON SMILE encoding, fast."
   :url "https://github.com/dakrone/cheshire"
   :license {:name "The MIT License"
             :url "http://opensource.org/licenses/MIT"
             :distribution :repo}
   :global-vars {*warn-on-reflection* false}
-  :dependencies [[com.fasterxml.jackson.core/jackson-core "2.13.3"]
-                 [com.fasterxml.jackson.dataformat/jackson-dataformat-smile "2.13.3"
+  :dependencies [[com.fasterxml.jackson.core/jackson-core "2.21.8"]
+                 [com.fasterxml.jackson.dataformat/jackson-dataformat-smile "2.21.8"
                   :exclusions [com.fasterxml.jackson.core/jackson-databind]]
-                 [com.fasterxml.jackson.dataformat/jackson-dataformat-cbor "2.13.3"
+                 [com.fasterxml.jackson.dataformat/jackson-dataformat-cbor "2.21.8"
                   :exclusions [com.fasterxml.jackson.core/jackson-databind]]
                  [tigris "0.1.2"]]
-  :profiles {:dev {:dependencies [[org.clojure/clojure "1.11.1"]
+  :profiles {:dev {:dependencies [[org.clojure/clojure "1.12.2"]
                                   [org.clojure/test.generative "0.1.4"]
                                   [org.clojure/tools.namespace "0.3.1"]]}
              :1.7 {:dependencies [[org.clojure/clojure "1.7.0"]]}
              :1.8 {:dependencies [[org.clojure/clojure "1.8.0"]]}
              :1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]}
              :1.10 {:dependencies [[org.clojure/clojure "1.10.3"]]}
+             :1.11 {:dependencies [[org.clojure/clojure "1.11.4"]]}
              :benchmark {:test-paths ["benchmarks"]
                          :jvm-opts ^:replace ["-Xms1g" "-Xmx1g" "-server"]
                          :dependencies [[criterium "0.4.6"]
@@ -26,19 +27,35 @@
   :aliases {"all" ["with-profile" "dev,1.7:dev,1.8:dev,1.9:dev,1.10:dev"]
             "benchmark" ["with-profile" "dev,benchmark" "test"]
             "pretty-bench" ["with-profile" "dev,benchmark" "test" ":only"
-                          "cheshire.test.benchmark/t-bench-pretty"]
+                            "cheshire.test.benchmark/t-bench-pretty"]
             "core-bench" ["with-profile" "dev,benchmark" "test" ":only"
-                          "cheshire.test.benchmark/t-bench-core"]}
+                          "cheshire.test.benchmark/t-bench-core"]
+            "clj-kondo-deps" ["with-profile" "+test" "clj-kondo" "--skip-lint" "--copy-configs" "--dependencies" "--parallel" "--lint" "$classpath"]
+            "clj-kondo-lint" ["do" ["clj-kondo-deps"] ["with-profile" "+test" "clj-kondo" "--parallel" "--lint" "src" "test" "project.clj"]]}
   :test-selectors {:default  #(and (not (:benchmark %))
                                    (not (:generative %)))
                    :generative :generative
                    :all (constantly true)}
-  :plugins [[codox "0.6.3"]
-            [lein-ancient "0.6.15"]]
+  :plugins [[com.github.liquidz/antq "2.11.1276"]
+            [jonase/eastwood "1.4.3"]
+            [com.github.clj-kondo/lein-clj-kondo "2025.04.07"]]
   :java-source-paths ["src/java"]
-  :jvm-opts ["-Xmx512M"
+  :jvm-opts ["-Xmx1024M"
 ;;             "-XX:+PrintCompilation"
 ;;             "-XX:+UnlockDiagnosticVMOptions"
 ;;             "-XX:+PrintInlining"
              ]
-  :javac-options ["-target" "1.7" "-source" "1.7" "-Xlint:-options"])
+  :eastwood {:namespaces [:source-paths]
+             :linters [:deprecations]}
+  :javac-options
+  ~(let [version (System/getProperty "java.version")
+        ;; Parse major version from strings like "1.8.0_292" or "11.0.11"
+         major (-> (re-find #"^(1\.)?(\d+)" version)
+                   (last)
+                   (Integer/parseInt))
+         target-opts (case major
+                       8 ["-source" "1.8" "-target" "1.8"]
+                       (if (>= major 9)
+                         ["--release" "8"]
+                         (throw (ex-info "javac needs a min of JDK 8" {}))))]
+     (into target-opts ["-Xlint:-options" "-Xlint:deprecation" "-Werror"])))


=====================================
src/cheshire/core.clj
=====================================
@@ -5,17 +5,17 @@
             [cheshire.generate-seq :as gen-seq]
             [cheshire.parse :as parse])
   (:import (com.fasterxml.jackson.core JsonParser JsonFactory
-                                       JsonGenerator PrettyPrinter
-                                       JsonGenerator$Feature)
+                                       JsonGenerator PrettyPrinter)
+           (com.fasterxml.jackson.core.json JsonWriteFeature)
            (com.fasterxml.jackson.dataformat.cbor CBORFactory)
            (com.fasterxml.jackson.dataformat.smile SmileFactory)
            (cheshire.prettyprint CustomPrettyPrinter)
-           (java.io StringWriter StringReader BufferedReader BufferedWriter
+           (java.io StringWriter StringReader BufferedReader
                     ByteArrayOutputStream OutputStream Reader Writer)))
 
 (defonce default-pretty-print-options
   {:indentation "  "
-   :line-break "\n"
+   :line-break (System/lineSeparator)
    :indent-arrays? false
    :indent-objects? true
    :before-array-values nil
@@ -69,8 +69,10 @@
          PrettyPrinter
            (.setPrettyPrinter generator print-pretty)
          nil))
-     (when (:escape-non-ascii opt-map)
-       (.enable generator JsonGenerator$Feature/ESCAPE_NON_ASCII))
+     ;; legacy fn opt, consider using fatory opt instead
+     (when (some? (:escape-non-ascii opt-map))
+       (.configure generator (.mappedFeature JsonWriteFeature/ESCAPE_NON_ASCII)
+                   (boolean (:escape-non-ascii opt-map))))
      (gen/generate generator obj
                    (or (:date-format opt-map) factory/default-date-format)
                    (:ex opt-map)
@@ -84,13 +86,13 @@
   objects will be encoded with.
 
   The default date format (in UTC) is: yyyy-MM-dd'T'HH:mm:ss'Z'"
-  (^BufferedWriter [obj ^BufferedWriter writer]
+  (^Writer [obj ^Writer writer]
    (generate-stream obj writer nil))
-  (^BufferedWriter [obj ^BufferedWriter writer opt-map]
+  (^Writer [obj ^Writer writer opt-map]
    (let [generator (.createGenerator
                     ^JsonFactory (or factory/*json-factory*
                                      factory/json-factory)
-                    ^Writer writer)
+                    writer)
          print-pretty (:pretty opt-map)]
      (when print-pretty
        (condp instance? print-pretty
@@ -101,8 +103,10 @@
          PrettyPrinter
        (.setPrettyPrinter generator print-pretty)
          nil))
-     (when (:escape-non-ascii opt-map)
-       (.enable generator JsonGenerator$Feature/ESCAPE_NON_ASCII))
+     ;; legacy fn opt, consider using fatory opt instead
+     (when (some? (:escape-non-ascii opt-map))
+       (.configure generator (.mappedFeature JsonWriteFeature/ESCAPE_NON_ASCII)
+                   (boolean (:escape-non-ascii opt-map))))
      (gen/generate generator obj (or (:date-format opt-map)
                                      factory/default-date-format)
                    (:ex opt-map)
@@ -118,8 +122,8 @@
                     factory/json-factory)
    ^Writer writer))
 
-(def ^:dynamic ^JsonGenerator *generator*)
-(def ^:dynamic *opt-map*)
+(def ^:dynamic ^JsonGenerator *generator* nil)
+(def ^:dynamic *opt-map* nil)
 
 (defmacro with-writer
   "Start writing for series objects using the same json generator.


=====================================
src/cheshire/custom.clj
=====================================
@@ -1,19 +1,17 @@
-(ns cheshire.custom
+(ns ^{:deprecated "5.0.0"} cheshire.custom
   "DEPRECATED
 
   Methods used for extending JSON generation to different Java classes.
   Has the same public API as core.clj so they can be swapped in and out."
-  (:use [cheshire.factory])
   (:require [cheshire.core :as core]
+            [cheshire.factory :as fact]
             [cheshire.generate :as generate])
   (:import (java.io BufferedWriter ByteArrayOutputStream StringWriter)
            (java.util Date SimpleTimeZone)
            (java.text SimpleDateFormat)
-           (java.sql Timestamp)
            (com.fasterxml.jackson.dataformat.smile SmileFactory)
-           (com.fasterxml.jackson.core JsonFactory JsonGenerator
-                                       JsonGenerator$Feature
-                                       JsonGenerationException JsonParser)))
+           (com.fasterxml.jackson.core JsonFactory JsonGenerator)
+           (com.fasterxml.jackson.core.json JsonWriteFeature)))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;;;;  DEPRECATED, DO NOT USE  ;;;;;;
@@ -21,11 +19,7 @@
 
 
 ;; date format rebound for custom encoding
-(def ^{:dynamic true :private true} *date-format*)
-
-;; pre-allocated exception for fast-failing core attempt for custom encoding
-(def ^{:private true} core-failure (JsonGenerationException.
-                                    "Cannot custom JSON encode object"))
+(def ^{:dynamic true :private true} *date-format* nil)
 
 (defprotocol JSONable
   (to-json [t jg]))
@@ -34,14 +28,15 @@
   (^String [obj]
      (encode* obj nil))
   (^String [obj opt-map]
-     (binding [*date-format* (or (:date-format opt-map) default-date-format)]
+     (binding [*date-format* (or (:date-format opt-map) fact/default-date-format)]
        (let [sw (StringWriter.)
-             generator (.createJsonGenerator
-                        ^JsonFactory (or *json-factory* json-factory) sw)]
+             generator (.createGenerator
+                        ^JsonFactory (or fact/*json-factory* fact/json-factory) sw)]
          (when (:pretty opt-map)
            (.useDefaultPrettyPrinter generator))
-         (when (:escape-non-ascii opt-map)
-           (.enable generator JsonGenerator$Feature/ESCAPE_NON_ASCII))
+         (when (some? (:escape-non-ascii opt-map))
+           (.configure generator (.mappedFeature JsonWriteFeature/ESCAPE_NON_ASCII)
+                       (boolean (:escape-non-ascii opt-map))))
          (if obj
            (to-json obj generator)
            (.writeNull generator))
@@ -55,17 +50,20 @@
   (^String [obj ^BufferedWriter w]
      (encode-stream* obj w nil))
   (^String [obj ^BufferedWriter w opt-map]
-     (binding [*date-format* (or (:date-format opt-map) default-date-format)]
-       (let [generator (.createJsonGenerator
-                        ^JsonFactory (or *json-factory* json-factory) w)]
+     (binding [*date-format* (or (:date-format opt-map) fact/default-date-format)]
+       (let [generator (.createGenerator
+                        ^JsonFactory (or fact/*json-factory* fact/json-factory) w)]
          (when (:pretty opt-map)
            (.useDefaultPrettyPrinter generator))
-         (when (:escape-non-ascii opt-map)
-           (.enable generator JsonGenerator$Feature/ESCAPE_NON_ASCII))
+         (when (some? (:escape-non-ascii opt-map))
+           (.configure generator (.mappedFeature JsonWriteFeature/ESCAPE_NON_ASCII)
+                       (boolean (:escape-non-ascii opt-map))))
          (to-json obj generator)
          (.flush generator)
          w))))
 
+
+
 (def encode-stream encode-stream*)
 (core/copy-arglists encode-stream encode-stream*)
 
@@ -73,10 +71,10 @@
   (^bytes [obj]
      (encode-smile* obj nil))
   (^bytes [obj opt-map]
-     (binding [*date-format* (or (:date-format opt-map) default-date-format)]
+     (binding [*date-format* (or (:date-format opt-map) fact/default-date-format)]
        (let [baos (ByteArrayOutputStream.)
-             generator (.createJsonGenerator ^SmileFactory
-                                             (or *smile-factory* smile-factory)
+             generator (.createGenerator ^SmileFactory
+                                             (or fact/*smile-factory* fact/smile-factory)
                                              baos)]
          (to-json obj generator)
          (.flush generator)


=====================================
src/cheshire/exact.clj
=====================================
@@ -2,7 +2,7 @@
   (:require [cheshire.factory :as factory]
             [cheshire.parse :as parse]
             [cheshire.core :as core])
-  (:import (java.io StringReader Reader BufferedReader
+  (:import (java.io StringReader Reader
                     Writer)
            (com.fasterxml.jackson.core JsonFactory)))
 


=====================================
src/cheshire/experimental.clj
=====================================
@@ -1,7 +1,6 @@
 (ns cheshire.experimental
   "Experimental JSON encoding/decoding tools."
-  (:require [cheshire.core :refer :all]
-            [clojure.java.io :refer :all]
+  (:require [cheshire.core :as json]
             [tigris.core :refer [str-escaping-input-stream]])
   (:import (java.io ByteArrayInputStream SequenceInputStream)))
 
@@ -19,8 +18,8 @@
   ([obj field stream]
      (encode-large-field-in-map obj field stream nil))
   ([obj field stream & [opt-map]]
-     (let [otherstr (encode (dissoc obj field) opt-map)
-           truncstr (str (subs otherstr 0 (dec (count otherstr))))
+     (let [otherstr (json/encode (dissoc obj field) opt-map)
+           truncstr (subs otherstr 0 (dec (count otherstr)))
            stream (str-escaping-input-stream stream)
            pre-stream (ByteArrayInputStream.
                        (.getBytes (str truncstr ",\"" (name field) "\":\"")))


=====================================
src/cheshire/factory.clj
=====================================
@@ -3,9 +3,11 @@
  custom generators."
   (:import (com.fasterxml.jackson.dataformat.smile SmileFactory)
            (com.fasterxml.jackson.dataformat.cbor CBORFactory)
-           (com.fasterxml.jackson.core JsonFactory JsonFactory$Feature
-                                       JsonParser$Feature
-                                       JsonGenerator$Feature)))
+           (com.fasterxml.jackson.core TSFBuilder JsonFactory JsonFactory$Feature
+                                       StreamReadFeature
+                                       StreamReadConstraints StreamWriteConstraints)
+           (com.fasterxml.jackson.core.json JsonReadFeature
+                                            JsonWriteFeature)))
 
 ;; default date format used to JSON-encode Date objects
 (def default-date-format "yyyy-MM-dd'T'HH:mm:ss'Z'")
@@ -19,94 +21,89 @@
    :allow-backslash-escaping false
    :allow-numeric-leading-zeros false
    :allow-non-numeric-numbers false
+   :allow-trailing-comma false
    :intern-field-names false
    :canonicalize-field-names false
+   :escape-non-ascii false
    :quote-field-names true
-   :strict-duplicate-detection false})
+   :strict-duplicate-detection false
+   ;; default values from Jackson 2.18.3
+   ;; as of this version seem to be enforced for json only and not cbor, smile
+   :max-input-document-length nil ;; no limit by default
+   :max-input-token-count nil     ;; no limit by default
+   :max-input-name-length 50000
+   :max-input-nesting-depth 1000
+   :max-input-number-length 1000
+   :max-input-string-length 20000000
+   :max-output-nesting-depth 1000})
 
-;; Factory objects that are needed to do the encoding and decoding
-(defn make-json-factory
-  ^JsonFactory [opts]
-  (let [opts (merge default-factory-options opts)]
-    (doto (JsonFactory.)
-      (.configure JsonParser$Feature/AUTO_CLOSE_SOURCE
+(defn- apply-base-opts ^TSFBuilder [^TSFBuilder builder opts]
+  (-> builder
+      (.configure StreamReadFeature/AUTO_CLOSE_SOURCE
                   (boolean (:auto-close-source opts)))
-      (.configure JsonParser$Feature/ALLOW_COMMENTS
-                  (boolean (:allow-comments opts)))
-      (.configure JsonParser$Feature/ALLOW_UNQUOTED_FIELD_NAMES
-                  (boolean (:allow-unquoted-field-names opts)))
-      (.configure JsonParser$Feature/ALLOW_SINGLE_QUOTES
-                  (boolean (:allow-single-quotes opts)))
-      (.configure JsonParser$Feature/ALLOW_UNQUOTED_CONTROL_CHARS
-                  (boolean (:allow-unquoted-control-chars opts)))
-      (.configure JsonParser$Feature/ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER
-                  (boolean (:allow-backslash-escaping opts)))
-      (.configure JsonParser$Feature/ALLOW_NUMERIC_LEADING_ZEROS
-                  (boolean (:allow-numeric-leading-zeros opts)))
-      (.configure JsonParser$Feature/ALLOW_NON_NUMERIC_NUMBERS
-                  (boolean (:allow-non-numeric-numbers opts)))
-      (.configure JsonParser$Feature/STRICT_DUPLICATE_DETECTION
+      (.configure StreamReadFeature/STRICT_DUPLICATE_DETECTION
                   (boolean (:strict-duplicate-detection opts)))
       (.configure JsonFactory$Feature/INTERN_FIELD_NAMES
                   (boolean (:intern-field-names opts)))
       (.configure JsonFactory$Feature/CANONICALIZE_FIELD_NAMES
                   (boolean (:canonicalize-field-names opts)))
-      (.configure JsonGenerator$Feature/QUOTE_FIELD_NAMES
-                  (boolean (:quote-field-names opts))))))
+      (.streamReadConstraints (-> (StreamReadConstraints/builder)
+                                  (.maxDocumentLength (or (:max-input-document-length opts) -1))
+                                  (.maxTokenCount (or (:max-input-token-count opts) -1))
+                                  (.maxNameLength (:max-input-name-length opts))
+                                  (.maxNestingDepth (:max-input-nesting-depth opts))
+                                  (.maxNumberLength (:max-input-number-length opts))
+                                  (.maxStringLength (:max-input-string-length opts))
+                                  (.build)))
+      (.streamWriteConstraints (-> (StreamWriteConstraints/builder)
+                                   (.maxNestingDepth (:max-output-nesting-depth opts))
+                                   (.build)))))
 
-(defn make-smile-factory
-  ^SmileFactory [opts]
-  (let [opts (merge default-factory-options opts)]
-    (doto (SmileFactory.)
-      (.configure JsonParser$Feature/AUTO_CLOSE_SOURCE
-                  (boolean (:auto-close-source opts)))
-      (.configure JsonParser$Feature/ALLOW_COMMENTS
+(defn- apply-json-opts ^TSFBuilder [^TSFBuilder builder opts]
+  (-> builder
+      (.configure JsonReadFeature/ALLOW_JAVA_COMMENTS
                   (boolean (:allow-comments opts)))
-      (.configure JsonParser$Feature/ALLOW_UNQUOTED_FIELD_NAMES
+      (.configure JsonReadFeature/ALLOW_UNQUOTED_FIELD_NAMES
                   (boolean (:allow-unquoted-field-names opts)))
-      (.configure JsonParser$Feature/ALLOW_SINGLE_QUOTES
+      (.configure JsonReadFeature/ALLOW_SINGLE_QUOTES
                   (boolean (:allow-single-quotes opts)))
-      (.configure JsonParser$Feature/ALLOW_UNQUOTED_CONTROL_CHARS
+      (.configure JsonReadFeature/ALLOW_UNESCAPED_CONTROL_CHARS
                   (boolean (:allow-unquoted-control-chars opts)))
-      (.configure JsonParser$Feature/ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER
+      (.configure JsonReadFeature/ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER
                   (boolean (:allow-backslash-escaping opts)))
-      (.configure JsonParser$Feature/ALLOW_NUMERIC_LEADING_ZEROS
+      (.configure JsonReadFeature/ALLOW_LEADING_ZEROS_FOR_NUMBERS
                   (boolean (:allow-numeric-leading-zeros opts)))
-      (.configure JsonParser$Feature/ALLOW_NON_NUMERIC_NUMBERS
+      (.configure JsonReadFeature/ALLOW_NON_NUMERIC_NUMBERS
                   (boolean (:allow-non-numeric-numbers opts)))
-      (.configure JsonFactory$Feature/INTERN_FIELD_NAMES
-                  (boolean (:intern-field-names opts)))
-      (.configure JsonFactory$Feature/CANONICALIZE_FIELD_NAMES
-                  (boolean (:canonicalize-field-names opts)))
-      (.configure JsonGenerator$Feature/QUOTE_FIELD_NAMES
-                  (boolean (:quote-field-names opts))))))
+      (.configure JsonReadFeature/ALLOW_TRAILING_COMMA
+                  (boolean (:allow-trailing-comma opts)))
+      (.configure JsonWriteFeature/QUOTE_FIELD_NAMES
+                  (boolean (:quote-field-names opts)))
+      (.configure JsonWriteFeature/ESCAPE_NON_ASCII
+                  (boolean (:escape-non-ascii opts)))))
+
+;; Factory objects that are needed to do the encoding and decoding
+(defn make-json-factory
+  ^JsonFactory [opts]
+  (let [opts (merge default-factory-options opts)]
+    (-> (JsonFactory/builder)
+        (apply-base-opts opts)
+        (apply-json-opts opts)
+        (.build))))
+
+(defn make-smile-factory
+  ^SmileFactory [opts]
+  (let [opts (merge default-factory-options opts)]
+    (-> (SmileFactory/builder)
+        (apply-base-opts opts)
+        (.build))))
 
 (defn make-cbor-factory
   ^CBORFactory [opts]
   (let [opts (merge default-factory-options opts)]
-    (doto (CBORFactory.)
-      (.configure JsonParser$Feature/AUTO_CLOSE_SOURCE
-                  (boolean (:auto-close-source opts)))
-      (.configure JsonParser$Feature/ALLOW_COMMENTS
-                  (boolean (:allow-comments opts)))
-      (.configure JsonParser$Feature/ALLOW_UNQUOTED_FIELD_NAMES
-                  (boolean (:allow-unquoted-field-names opts)))
-      (.configure JsonParser$Feature/ALLOW_SINGLE_QUOTES
-                  (boolean (:allow-single-quotes opts)))
-      (.configure JsonParser$Feature/ALLOW_UNQUOTED_CONTROL_CHARS
-                  (boolean (:allow-unquoted-control-chars opts)))
-      (.configure JsonParser$Feature/ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER
-                  (boolean (:allow-backslash-escaping opts)))
-      (.configure JsonParser$Feature/ALLOW_NUMERIC_LEADING_ZEROS
-                  (boolean (:allow-numeric-leading-zeros opts)))
-      (.configure JsonParser$Feature/ALLOW_NON_NUMERIC_NUMBERS
-                  (boolean (:allow-non-numeric-numbers opts)))
-      (.configure JsonFactory$Feature/INTERN_FIELD_NAMES
-                  (boolean (:intern-field-names opts)))
-      (.configure JsonFactory$Feature/CANONICALIZE_FIELD_NAMES
-                  (boolean (:canonicalize-field-names opts)))
-      (.configure JsonGenerator$Feature/QUOTE_FIELD_NAMES
-                  (boolean (:quote-field-names opts))))))
+    (-> (CBORFactory/builder)
+        (apply-base-opts opts)
+        (.build))))
 
 (defonce ^JsonFactory json-factory (make-json-factory default-factory-options))
 (defonce ^SmileFactory smile-factory


=====================================
src/cheshire/generate.clj
=====================================
@@ -4,11 +4,13 @@
            (java.util Date Map List Set SimpleTimeZone UUID)
            (java.sql Timestamp)
            (java.text SimpleDateFormat)
+           (java.time Instant)
            (java.math BigInteger)
-           (clojure.lang IPersistentCollection Keyword Ratio Symbol)))
+           (java.util.concurrent.atomic AtomicInteger AtomicLong)
+           (clojure.lang  Keyword Ratio Symbol)))
 
 ;; date format rebound for custom encoding
-(def ^{:dynamic true :private true} *date-format*)
+(def ^{:dynamic true :private true} *date-format* nil)
 
 (defmacro tag
   ([obj]
@@ -26,7 +28,8 @@
      (catch IllegalArgumentException _#
        (throw (or ~e (JsonGenerationException.
                       (str "Cannot JSON encode object of class: "
-                           (class ~obj) ": " ~obj)))))))
+                           (class ~obj) ": " ~obj)
+                      ~jg))))))
 
 (defmacro number-dispatch [jg obj e]
   (let [g (tag (gensym 'jg))
@@ -41,7 +44,9 @@
                                      ~g ~(with-meta o {:tag `BigDecimal}))
                          Ratio (.writeNumber ~g (double ~o))
                          Short (.writeNumber ~g (int ~o))
-                         Byte (.writeNumber ~g (int ~o))]]
+                         Byte (.writeNumber ~g (int ~o))
+                         AtomicLong (.writeNumber ~g (long ~o))
+                         AtomicInteger (.writeNumber ~g (int ~o))]]
     `(let [~g ~jg
            ~o ~obj]
        (condp instance? ~o
@@ -75,7 +80,6 @@
 (definline generate-key-fn-map
   [^JsonGenerator jg obj ^String date-format ^Exception e key-fn]
   (let [k (gensym 'k)
-        name (gensym 'name)
         jg (tag jg)]
     `(do
        (.writeStartObject ~jg)
@@ -148,10 +152,13 @@
    (i? Date obj) (let [sdf (doto (SimpleDateFormat. date-format)
                              (.setTimeZone (SimpleTimeZone. 0 "UTC")))]
                    (write-string ^JsonGenerator jg (.format sdf obj)))
-   (i? Timestamp obj) (let [date (Date. (.getTime ^Timestamp obj))
-                            sdf (doto (SimpleDateFormat. date-format)
+   (i? Timestamp obj) (let [sdf (doto (SimpleDateFormat. date-format)
                                   (.setTimeZone (SimpleTimeZone. 0 "UTC")))]
                         (write-string ^JsonGenerator jg (.format sdf obj)))
+   (i? Instant obj) (let [sdf (doto (SimpleDateFormat. date-format)
+                                (.setTimeZone (SimpleTimeZone. 0 "UTC")))
+                          d (Date/from obj)]
+                      (write-string ^JsonGenerator jg (.format sdf d)))
    :else (fail obj jg ex)))
 
 ;; Generic encoders, these can be used by someone writing a custom


=====================================
src/cheshire/generate_seq.clj
=====================================
@@ -1,15 +1,13 @@
 (ns cheshire.generate-seq
   "Namespace used to generate JSON from Clojure data structures in a
   sequential way."
-  (:use [cheshire.generate :only [tag JSONable to-json i?
-                                  number-dispatch write-string
-                                  fail]])
-  (:import (com.fasterxml.jackson.core JsonGenerator JsonGenerationException)
+  (:require [cheshire.generate :as g])
+  (:import (com.fasterxml.jackson.core JsonGenerator)
            (java.util Date Map List Set SimpleTimeZone UUID)
            (java.sql Timestamp)
            (java.text SimpleDateFormat)
-           (java.math BigInteger)
-           (clojure.lang IPersistentCollection Keyword Ratio Symbol)))
+           (java.time Instant)
+           (clojure.lang IPersistentCollection Keyword Symbol)))
 
 (definline write-start-object [^JsonGenerator jg wholeness]
   `(if (contains? #{:all :start :start-inner} ~wholeness)
@@ -32,7 +30,7 @@
 (definline generate-basic-map
   [^JsonGenerator jg obj ^String date-format ^Exception e
    wholeness]
-  (let [jg (tag jg)]
+  (let [jg (g/tag jg)]
     `(do
        (write-start-object ~jg ~wholeness)
        (reduce (fn [^JsonGenerator jg# kv#]
@@ -53,8 +51,7 @@
   [^JsonGenerator jg obj ^String date-format ^Exception e
    key-fn wholeness]
   (let [k (gensym 'k)
-        name (gensym 'name)
-        jg (tag jg)]
+        jg (g/tag jg)]
     `(do
        (write-start-object ~jg ~wholeness)
        (reduce (fn [^JsonGenerator jg# kv#]
@@ -81,7 +78,7 @@
 
 (definline generate-array [^JsonGenerator jg obj ^String date-format
                            ^Exception e key-fn wholeness]
-  (let [jg (tag jg)]
+  (let [jg (g/tag jg)]
     `(do
        (write-start-array ~jg ~wholeness)
        (reduce (fn [jg# item#]
@@ -98,9 +95,9 @@
   (let [wholeness (or wholeness :all)]
     (cond
      (nil? obj) (.writeNull ^JsonGenerator jg)
-     (get (:impls JSONable) (class obj)) (#'to-json obj jg)
+     (get (:impls g/JSONable) (class obj)) (#'g/to-json obj jg)
 
-     (i? IPersistentCollection obj)
+     (g/i? IPersistentCollection obj)
      (condp instance? obj
        clojure.lang.IPersistentMap
        (generate-map jg obj date-format ex key-fn wholeness)
@@ -115,21 +112,24 @@
        clojure.lang.Associative
        (generate-map jg obj date-format ex key-fn wholeness))
 
-     (i? Number obj) (number-dispatch ^JsonGenerator jg obj ex)
-     (i? Boolean obj) (.writeBoolean ^JsonGenerator jg ^Boolean obj)
-     (i? String obj) (write-string ^JsonGenerator jg ^String obj)
-     (i? Character obj) (write-string ^JsonGenerator jg ^String (str obj))
-     (i? Keyword obj) (write-string ^JsonGenerator jg (.substring (str obj) 1))
-     (i? Map obj) (generate-map jg obj date-format ex key-fn wholeness)
-     (i? List obj) (generate-array jg obj date-format ex key-fn wholeness)
-     (i? Set obj) (generate-array jg obj date-format ex key-fn wholeness)
-     (i? UUID obj) (write-string ^JsonGenerator jg (.toString ^UUID obj))
-     (i? Symbol obj) (write-string ^JsonGenerator jg (.toString ^Symbol obj))
-     (i? Date obj) (let [sdf (doto (SimpleDateFormat. date-format)
+     (g/i? Number obj) (g/number-dispatch ^JsonGenerator jg obj ex)
+     (g/i? Boolean obj) (.writeBoolean ^JsonGenerator jg ^Boolean obj)
+     (g/i? String obj) (g/write-string ^JsonGenerator jg ^String obj)
+     (g/i? Character obj) (g/write-string ^JsonGenerator jg ^String (str obj))
+     (g/i? Keyword obj) (g/write-string ^JsonGenerator jg (.substring (str obj) 1))
+     (g/i? Map obj) (generate-map jg obj date-format ex key-fn wholeness)
+     (g/i? List obj) (generate-array jg obj date-format ex key-fn wholeness)
+     (g/i? Set obj) (generate-array jg obj date-format ex key-fn wholeness)
+     (g/i? UUID obj) (g/write-string ^JsonGenerator jg (.toString ^UUID obj))
+     (g/i? Symbol obj) (g/write-string ^JsonGenerator jg (.toString ^Symbol obj))
+     (g/i? Date obj) (let [sdf (doto (SimpleDateFormat. date-format)
                                (.setTimeZone (SimpleTimeZone. 0 "UTC")))]
-                     (write-string ^JsonGenerator jg (.format sdf obj)))
-     (i? Timestamp obj) (let [date (Date. (.getTime ^Timestamp obj))
-                              sdf (doto (SimpleDateFormat. date-format)
-                                    (.setTimeZone (SimpleTimeZone. 0 "UTC")))]
-                          (write-string ^JsonGenerator jg (.format sdf obj)))
-     :else (fail obj jg ex))))
+                     (g/write-string ^JsonGenerator jg (.format sdf obj)))
+     (g/i? Timestamp obj) (let [sdf (doto (SimpleDateFormat. date-format)
+                                      (.setTimeZone (SimpleTimeZone. 0 "UTC")))]
+                            (g/write-string ^JsonGenerator jg (.format sdf obj)))
+     (g/i? Instant obj) (let [sdf (doto (SimpleDateFormat. date-format)
+                                    (.setTimeZone (SimpleTimeZone. 0 "UTC")))
+                              d (Date/from obj)]
+                          (g/write-string ^JsonGenerator jg (.format sdf d)))
+     :else (g/fail obj jg ex))))


=====================================
src/cheshire/parse.clj
=====================================
@@ -32,7 +32,7 @@
 
 (definline parse-array [^JsonParser jp key-fn bd? array-coerce-fn]
   (let [jp (tag jp)]
-    `(let [array-field-name# (.getCurrentName ~jp)]
+    `(let [array-field-name# (.currentName ~jp)]
        (.nextToken ~jp)
        (loop [coll# (transient (if ~array-coerce-fn
                                  (~array-coerce-fn array-field-name#)


=====================================
test/cheshire/test/core.clj
=====================================
@@ -1,17 +1,39 @@
 (ns cheshire.test.core
-  (:use [clojure.test]
-        [clojure.java.io :only [file reader]])
-  (:require [cheshire.core :as json]
+  (:require [clojure.test :refer [deftest testing is are]]
+            [clojure.java.io :as io]
+            [clojure.string :as str]
+            [cheshire.core :as json]
             [cheshire.exact :as json-exact]
             [cheshire.generate :as gen]
             [cheshire.factory :as fact]
             [cheshire.parse :as parse])
   (:import (com.fasterxml.jackson.core JsonGenerationException
                                        JsonParseException)
+           (com.fasterxml.jackson.core.exc StreamConstraintsException)
            (java.io FileInputStream StringReader StringWriter
-                    BufferedReader BufferedWriter)
+                    BufferedReader BufferedWriter
+                    IOException)
            (java.sql Timestamp)
-           (java.util Date UUID)))
+           (java.time Instant)
+           (java.util Date UUID)
+           (java.util.concurrent.atomic AtomicInteger AtomicLong)))
+
+(defn- str-of-len
+  ([len]
+   (str-of-len len "x"))
+  ([len val]
+   (apply str (repeat len val))))
+
+(defn- nested-map [depth]
+  (reduce (fn [acc n] {(str n) acc})
+          {"0" "foo"}
+          (range 1 depth)))
+
+(defn- encode-stream->str [obj opts]
+  (let [sw (StringWriter.)
+        bw (BufferedWriter. sw)]
+    (json/generate-stream obj bw opts)
+    (.toString sw)))
 
 (def test-obj {"int" 3 "long" (long -2147483647) "boolean" true
                "LongObj" (Long/parseLong "2147483647") "double" 1.23
@@ -39,6 +61,24 @@
     (binding [parse/*use-bigdecimals?* true]
       (is (= n (:num (json/decode (json/encode {:num n}) true)))))))
 
+(deftest test-atomic-long
+  (is (= {"x" 42}
+         (json/decode (json/encode {:x (AtomicLong. 42)}))))
+  (is (= {"x" 42}
+         (json/decode
+          (str
+           (json/with-writer [(StringWriter.) nil]
+             (json/write {:x (AtomicLong. 42)})))))))
+
+(deftest test-atomic-integer
+  (is (= {"y" 14}
+         (json/decode (json/encode {:y (AtomicInteger. 14)}))))
+  (is (= {"y" 14}
+         (json/decode
+          (str
+           (json/with-writer [(StringWriter.) nil]
+             (json/write {:y (AtomicInteger. 14)})))))))
+
 (deftest test-string-round-trip
   (is (= test-obj (json/decode (json/encode test-obj)))))
 
@@ -111,13 +151,52 @@
 (def bin-obj {"byte-array" (byte-array (map byte [1 2 3]))})
 
 (deftest test-round-trip-binary
-  (for [[p g] {json/parse-string json/generate-string
-               json/parse-smile  json/generate-smile
-               json/parse-cbor   json/generate-cbor}]
+  (doseq [[p g] {json/parse-string json/generate-string
+                 json/parse-smile  json/generate-smile
+                 json/parse-cbor   json/generate-cbor}]
     (is (let [roundtripped (p (g bin-obj))]
           ;; test value equality
-          (= (->> bin-obj (get "byte-array") seq)
-             (->> roundtripped (get "byte-array") seq))))))
+          (is (= (->> bin-obj (get "byte-array") seq)
+                 (->> roundtripped (get "byte-array") seq)))))))
+
+(deftest test-smile-factory
+  (binding [fact/*smile-factory* (fact/make-smile-factory {})]
+    (is (= {"a" 1} (-> {:a 1}
+                      json/generate-smile
+                      json/parse-smile)))))
+
+(deftest test-smile-duplicate-detection
+  (let [smile-data (byte-array [0x3a 0x29 0x0a 0x01 ;; smile header
+                                0xFa                ;; object start
+                                0x80 0x61           ;; key a
+                                0xC2                ;; value 1
+                                0x80 0x61           ;; key a (again)
+                                0xC4                ;; value 2
+                                0xFB                ;; object end
+                                ])]
+    (binding [fact/*smile-factory* (fact/make-smile-factory {:strict-duplicate-detection false})]
+      (is (= {"a" 2} (json/parse-smile smile-data))))
+    (binding [fact/*smile-factory* (fact/make-smile-factory {:strict-duplicate-detection true})]
+      (is (thrown? JsonParseException (json/parse-smile smile-data))))))
+
+(deftest test-cbor-factory
+  (binding [fact/*cbor-factory* (fact/make-cbor-factory {})]
+    (is (= {"a" 1} (-> {:a 1}
+                       json/generate-cbor
+                       json/parse-cbor)))))
+
+(deftest test-cbor-duplicate-detection
+  (let [cbor-data (byte-array [0xbf         ;; object begin
+                               0x61 0x61    ;; key a
+                               0x01         ;; value 1
+                               0x61 0x61    ;; key a (again)
+                               0x02         ;; value 2
+                               0xff         ;; object end
+                               ])]
+    (binding [fact/*cbor-factory* (fact/make-cbor-factory {:strict-duplicate-detection false})]
+      (is (= {"a" 2} (json/parse-cbor cbor-data))))
+    (binding [fact/*cbor-factory* (fact/make-cbor-factory {:strict-duplicate-detection true})]
+      (is (thrown? JsonParseException (json/parse-cbor cbor-data))))))
 
 (deftest test-aliases
   (is (= {"foo" "bar" "1" "bat" "2" "bang" "3" "biz"}
@@ -141,6 +220,30 @@
                                    {:date-format "yyyy-MM-dd"})))
       "encode with given date format"))
 
+(deftest test-instant
+  (is (= {"foo" "1970-01-01T00:00:00Z"}
+         (json/decode (json/encode {:foo (Instant/ofEpochSecond (long 0))}))))
+  (is (= {"foo" "1970-01-01"}
+         (json/decode (json/encode {:foo (Instant/ofEpochSecond (long 0))}
+                                   {:date-format "yyyy-MM-dd"})))
+      "encode with given date format")
+  (is (= {"foo" "1970-01-01-0004"}
+         (json/decode (json/encode {:foo (Instant/ofEpochSecond (long 0))}
+                                   {:date-format "yyyy-MM-dd-uuuu"})))
+      "use [[java.text.SimpleDateFormat]] format rules")
+
+  (is (= {"foo" "1970-01-01T00:00:00Z"}
+         (json/decode
+          (str (json/with-writer [(StringWriter.) nil]
+                 (json/write {:foo (Instant/ofEpochSecond (long 0))}))))))
+
+  (is (= {"foo" "1970-01-01"}
+         (json/decode
+          (str
+           (json/with-writer [(StringWriter.) {:date-format "yyyy-MM-dd"}]
+             (json/write {:foo (Instant/ofEpochSecond (long 0))})))))
+      "write with given date format"))
+
 (deftest test-uuid
   (let [id (UUID/randomUUID)
         id-str (str id)]
@@ -212,11 +315,11 @@
 
 (deftest test-multiple-objs-in-file
   (is (= {"one" 1, "foo" "bar"}
-         (first (json/parsed-seq (reader "test/multi.json")))))
+         (first (json/parsed-seq (io/reader "test/multi.json")))))
   (is (= {"two" 2, "foo" "bar"}
-         (second (json/parsed-seq (reader "test/multi.json")))))
-  (with-open [s (FileInputStream. (file "test/multi.json"))]
-    (let [r (reader s)]
+         (second (json/parsed-seq (io/reader "test/multi.json")))))
+  (with-open [s (FileInputStream. (io/file "test/multi.json"))]
+    (let [r (io/reader s)]
       (is (= [{"one" 1, "foo" "bar"} {"two" 2, "foo" "bar"}]
              (json/parsed-seq r))))))
 
@@ -245,16 +348,142 @@
   (is (= "{\"bar\":\"clojure.core/pam\",\"foo\":\"foo.bar/baz\"}"
          (json/encode (sorted-map :foo 'foo.bar/baz :bar 'clojure.core/pam)))))
 
-(deftest t-bindable-factories
+(deftest t-bindable-factories-auto-close-source
   (binding [fact/*json-factory* (fact/make-json-factory
-                                 {:allow-non-numeric-numbers true})]
-    (is (= (type Double/NaN)
-           (type (:foo (json/decode "{\"foo\":NaN}" true)))))))
+                                 {:auto-close-source false})]
+    (let [br (BufferedReader. (StringReader. "123"))]
+      (is (= 123 (json/parse-stream br)))
+      (is (= -1 (.read br)))))
+  (binding [fact/*json-factory* (fact/make-json-factory
+                                 {:auto-close-source true})]
+    (let [br (BufferedReader. (StringReader. "123"))]
+      (is (= 123 (json/parse-stream br)))
+      (is (thrown? IOException (.read br))))))
+
+(deftest t-bindable-factories-allow-comments
+  (let [s "{\"a\": /* comment */ 1, // comment\n \"b\": 2}"]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                   {:allow-comments true})]
+      (is (= {"a" 1 "b" 2} (json/decode s))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                   {:allow-comments false})]
+      (is (thrown? JsonParseException (json/decode s))))))
+
+(deftest t-bindable-factories-allow-unquoted-field-names
+  (let [s "{a: 1, b: 2}"]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                   {:allow-unquoted-field-names true})]
+      (is (= {"a" 1 "b" 2} (json/decode s))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                   {:allow-unquoted-field-names false})]
+      (is (thrown? JsonParseException (json/decode s))))))
+
+(deftest t-bindable-factories-allow-single-quotes
+  (doseq [s ["{'a': \"one\", 'b': \"two\"}"
+             "{\"a\": 'one', \"b\": 'two'}"
+             "{'a': 'one', 'b': 'two'}"]]
+    (testing s
+      (binding [fact/*json-factory* (fact/make-json-factory
+                                      {:allow-single-quotes true})]
+        (is (= {"a" "one" "b" "two"} (json/decode s))))
+      (binding [fact/*json-factory* (fact/make-json-factory
+                                      {:allow-single-quotes false})]
+        (is (thrown? JsonParseException (json/decode s)))))))
+
+(deftest t-bindable-factories-allow-unquoted-control-chars
+  (let [s "{\"a\": \"one\ntwo\"}"]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:allow-unquoted-control-chars true})]
+      (is (= {"a" "one\ntwo"} (json/decode s))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:allow-unquoted-control-chars false})]
+      (is (thrown? JsonParseException (json/decode s))))))
+
+(deftest t-bindable-factories-allow-numeric-leading-zeros
+  (let [s "{\"a\": 00000000001}"]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:allow-numeric-leading-zeros true})]
+      (is (= {"a" 1} (json/decode s))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:allow-numeric-leading-zeros false})]
+      (is (thrown? JsonParseException (json/decode s))))))
+
+(deftest t-bindable-factories-allow-backslash-escaping-any-char
+  (let [s "{\"a\": \"\\o\\n\\e\"}"]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:allow-backslash-escaping true})]
+      (is (= {"a" "o\ne"} (json/decode s))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:allow-backslash-escaping false})]
+      (is (thrown? JsonParseException (json/decode s))))))
+
+(deftest t-bindable-factories-non-numeric-numbers
+  (let [s "{\"foo\":NaN}"]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:allow-non-numeric-numbers true})]
+      (is (= (type Double/NaN)
+             (type (:foo (json/decode s true))))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:allow-non-numeric-numbers false})]
+      (is (thrown? JsonParseException (json/decode s true))))))
+
+(deftest t-bindable-factories-allow-trailing-comma
+  (let [s "{\"foo\":\"bar\",}"]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                   {:allow-trailing-comma true})]
+      (is (= "bar"
+             (:foo (json/decode s true)))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                   {:allow-trailing-comma false})]
+      (is (thrown? JsonParseException (json/decode s true))))))
+
+(deftest t-bindable-factories-optimization-opts
+  (let [s "{\"a\": \"foo\"}"]
+    (doseq [opts [{:intern-field-names true}
+                  {:intern-field-names false}
+                  {:canonicalize-field-names true}
+                  {:canonicalize-field-names false}]]
+      (binding [fact/*json-factory* (fact/make-json-factory opts)]
+        (is (= {"a" "foo"} (json/decode s)))))))
+
+(deftest t-bindable-factories-escape-non-ascii
+  ;; includes testing legacy fn opt of same name can override factory
+  (let [edn {:foo "It costs £100"}
+        expected-esc "{\"foo\":\"It costs \\u00A3100\"}"
+        expected-no-esc "{\"foo\":\"It costs £100\"}"
+        opt-esc {:escape-non-ascii true}
+        opt-no-esc {:escape-non-ascii false}]
+    (testing "default factory"
+      (doseq [[fn-opts     expected]
+              [[{}         expected-no-esc]
+               [opt-esc    expected-esc]
+               [opt-no-esc expected-no-esc]]]
+        (testing fn-opts
+          (is (= expected (json/encode edn fn-opts) (encode-stream->str edn fn-opts))))))
+    (testing (str "factory: " opt-esc)
+      (binding [fact/*json-factory* (fact/make-json-factory opt-esc)]
+        (doseq [[fn-opts     expected]
+                [[{}         expected-esc]
+                 [opt-esc    expected-esc]
+                 [opt-no-esc expected-no-esc]]]
+          (testing (str "fn: " fn-opts)
+            (is (= expected (json/encode edn fn-opts) (encode-stream->str edn fn-opts)))))))
+    (testing (str "factory: " opt-no-esc)
+      (binding [fact/*json-factory* (fact/make-json-factory opt-no-esc)]
+        (doseq [[fn-opts     expected]
+                [[{}         expected-no-esc]
+                 [opt-esc    expected-esc]
+                 [opt-no-esc expected-no-esc]]]
+          (testing (str "fn: " fn-opts)
+            (is (= expected (json/encode edn fn-opts) (encode-stream->str edn fn-opts)))))))))
 
 (deftest t-bindable-factories-quoteless
+  (binding [fact/*json-factory* (fact/make-json-factory
+                                  {:quote-field-names true})]
+    (is (= "{\"a\":\"foo\"}" (json/encode {:a "foo"}))))
   (binding [fact/*json-factory* (fact/make-json-factory
                                   {:quote-field-names false})]
-    (is (= "{a:1}" (json/encode {:a 1})))))
+    (is (= "{a:\"foo\"}" (json/encode {:a "foo"})))))
 
 (deftest t-bindable-factories-strict-duplicate-detection
   (binding [fact/*json-factory* (fact/make-json-factory
@@ -267,16 +496,150 @@
     (is (= {"a" 3 "b" 2}
            (json/decode "{\"a\": 1, \"b\": 2, \"a\": 3}")))))
 
+(deftest t-bindable-factories-max-input-document-length
+  (let [edn {"a" (apply str (repeat 10000 "x"))}
+        sample-data (json/encode edn)]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-document-length (count sample-data)})]
+      (is (= edn (json/decode sample-data))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    ;; as per Jackson docs, limit is inexact, so dividing input length by 2 should do the trick
+                                    {:max-input-document-length (/ (count sample-data) 2)})]
+      (is (thrown-with-msg?
+            StreamConstraintsException #"(?i)document length .* exceeds"
+            (json/decode sample-data))))))
+
+(deftest t-bindable-factories-max-input-token-count
+  ;; A token is a single unit of input, such as a number, a string, an object start or end, or an array start or end.
+  (let [edn {"1" 2 "3" 4}
+        sample-data (json/encode edn)]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-token-count 6})]
+      (is (= edn (json/decode sample-data))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-token-count 5})]
+      (is (thrown-with-msg?
+            StreamConstraintsException #"(?i)token count .* exceeds"
+            (json/decode sample-data))))))
+
+(deftest t-bindable-factories-max-input-name-length
+  (let [k "somekey"
+        edn {k 1}
+        sample-data (json/encode edn)]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-name-length (count k)})]
+      (is (= edn (json/decode sample-data))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-name-length (dec (count k))})]
+      (is (thrown-with-msg?
+            StreamConstraintsException #"(?i)name .* exceeds"
+            (json/decode sample-data)))))
+  (let [default-limit (:max-input-name-length fact/default-factory-options)]
+    (let [k (str-of-len default-limit)
+          edn {k 1}
+          sample-data (json/encode edn)]
+      (is (= edn (json/decode sample-data))))
+    (let [k (str-of-len (inc default-limit))
+          sample-data (json/encode {k 1})]
+      (is (thrown-with-msg?
+            StreamConstraintsException #"(?i)name .* exceeds"
+            (json/decode sample-data))))))
+
+(deftest t-bindable-factories-input-nesting-depth
+  (let [edn (nested-map 100)
+        sample-data (json/encode edn)]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-nesting-depth 100})]
+      (is (= edn (json/decode sample-data))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-nesting-depth 99})]
+      (is (thrown-with-msg?
+            StreamConstraintsException #"(?i)nesting depth .* exceeds"
+            (json/decode sample-data))))))
+
+(deftest t-bindable-factories-max-input-number-length
+  (let [num 123456789
+        edn {"foo" num}
+        sample-data (json/encode edn)]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-number-length (-> num str count)})]
+      (is (= edn (json/decode sample-data))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-number-length (-> num str count dec)})]
+      (is (thrown-with-msg?
+            StreamConstraintsException #"(?i)number value length .* exceeds"
+            (json/decode sample-data)))))
+  (let [default-limit (:max-input-number-length fact/default-factory-options)]
+    (let [num (bigint (str-of-len default-limit 2))
+          edn {"foo" num}
+          sample-data (json/encode edn)]
+      (is (= edn (json/decode sample-data))))
+    (let [num (bigint (str-of-len (inc default-limit) 2))
+          sample-data (json/encode {"foo" num})]
+      (is (thrown-with-msg?
+            StreamConstraintsException #"(?i)number value length .* exceeds"
+            (json/decode sample-data))))))
+
+(deftest t-bindable-factories-max-input-string-length
+  (let [big-string (str-of-len 40000000)
+        edn {"big-string" big-string}
+        sample-data (json/encode edn)]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-string-length (count big-string)})]
+      (is (= edn (json/decode sample-data))))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-input-string-length (dec (count big-string))})]
+      (is (thrown-with-msg?
+            StreamConstraintsException #"(?i)string value length .* exceeds"
+            (json/decode sample-data)))))
+  (let [default-limit (:max-input-string-length fact/default-factory-options)]
+    (let [big-string (str-of-len default-limit)
+          edn {"big-string" big-string}
+          sample-data (json/encode edn)]
+      (is (= edn (json/decode sample-data))))
+    (let [big-string (str-of-len (inc default-limit))
+          sample-data (json/encode {"big-string" big-string})]
+      (is (thrown-with-msg?
+            StreamConstraintsException #"(?i)string value length .* exceeds"
+            (json/decode sample-data))))))
+
+(deftest t-bindable-factories-max-output-nesting-depth
+  (let [edn (nested-map 100)]
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-output-nesting-depth 100})]
+      (is (.contains (json/encode edn) "\"99\"")))
+    (binding [fact/*json-factory* (fact/make-json-factory
+                                    {:max-output-nesting-depth 99})]
+      (is (thrown-with-msg?
+            StreamConstraintsException #"(?i)nesting depth .* exceeds"
+            (json/encode edn))))))
+
 (deftest t-persistent-queue
-  (let [q (conj (clojure.lang.PersistentQueue/EMPTY) 1 2 3)]
+  (let [q (conj clojure.lang.PersistentQueue/EMPTY 1 2 3)]
     (is (= q (json/decode (json/encode q))))))
 
 (deftest t-pretty-print
-  (is (= (str "{\n  \"bar\" : [ {\n    \"baz\" : 2\n  }, "
-              "\"quux\", [ 1, 2, 3 ] ],\n  \"foo\" : 1\n}")
+  (is (= (str/join (System/lineSeparator)
+                   ["{"
+                    "  \"bar\" : [ {"
+                    "    \"baz\" : 2"
+                    "  }, \"quux\", [ 1, 2, 3 ] ],"
+                    "  \"foo\" : 1"
+                    "}"])
          (json/encode (sorted-map :foo 1 :bar [{:baz 2} :quux [1 2 3]])
                       {:pretty true}))))
 
+(deftest t-pretty-print-custom-linebreak
+  (is (= (str/join "foo"
+                   ["{"
+                    "  \"bar\" : [ {"
+                    "    \"baz\" : 2"
+                    "  }, \"quux\", [ 1, 2, 3 ] ],"
+                    "  \"foo\" : 1"
+                    "}"])
+         (json/encode (sorted-map :foo 1 :bar [{:baz 2} :quux [1 2 3]])
+                      {:pretty {:line-break "foo"}}))))
+
 (deftest t-pretty-print-illegal-argument
   ; just expecting this not to throw
   (json/encode {:foo "bar"}
@@ -303,17 +666,18 @@
                             :before-array-values ""
                             :after-array-values ""
                             :object-field-value-separator ": "}}
-        expected (str "{\n"
-                      "    \"bar\": {\n"
-                      "        \"baz\": [{\n"
-                      "            \"ulu\": \"mulu\"\n"
-                      "        }, {\n"
-                      "            \"moot\": \"foo\"\n"
-                      "        }, 3]\n"
-                      "    },\n"
-                      "    \"foo\": 1,\n"
-                      "    \"quux\": \"blub\"\n"
-                      "}")
+        expected (str/join (System/lineSeparator)
+                           ["{"
+                            "    \"bar\": {"
+                            "        \"baz\": [{"
+                            "            \"ulu\": \"mulu\""
+                            "        }, {"
+                            "            \"moot\": \"foo\""
+                            "        }, 3]"
+                            "    },"
+                            "    \"foo\": 1,"
+                            "    \"quux\": \"blub\""
+                            "}"])
         pretty-str (json/encode test-obj test-opts)]
 
     ; just to be easy on the eyes in case of error
@@ -338,10 +702,6 @@
       (println expected))
     (is (= expected pretty-str))))
 
-(deftest t-unicode-escaping
-  (is (= "{\"foo\":\"It costs \\u00A3100\"}"
-         (json/encode {:foo "It costs £100"} {:escape-non-ascii true}))))
-
 (deftest t-custom-keyword-fn
   (is (= {:FOO "bar"} (json/decode "{\"foo\": \"bar\"}"
                                    (fn [k] (keyword (.toUpperCase k))))))
@@ -392,41 +752,41 @@
 (deftest t-custom-helpers
   (let [thing (CTestR. :state)
         remove #(gen/remove-encoder CTestR)]
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-nil nil jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-nil nil jg)))
     (is (= nil (json/decode (json/encode thing) true)))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-str "foo" jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-str "foo" jg)))
     (is (= "foo" (json/decode (json/encode thing) true)))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-number 5 jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-number 5 jg)))
     (is (= 5 (json/decode (json/encode thing) true)))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-long 4 jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-long 4 jg)))
     (is (= 4 (json/decode (json/encode thing) true)))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-int 3 jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-int 3 jg)))
     (is (= 3 (json/decode (json/encode thing) true)))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-ratio 1/2 jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-ratio 1/2 jg)))
     (is (= 0.5 (json/decode (json/encode thing) true)))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-seq [:foo :bar] jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-seq [:foo :bar] jg)))
     (is (= ["foo" "bar"] (json/decode (json/encode thing) true)))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-date (Date. (long 0)) jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-date (Date. (long 0)) jg)))
     (binding [gen/*date-format* "yyyy-MM-dd'T'HH:mm:ss'Z'"]
       (is (= "1970-01-01T00:00:00Z" (json/decode (json/encode thing) true))))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-bool true jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-bool true jg)))
     (is (= true (json/decode (json/encode thing) true)))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-named :foo jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-named :foo jg)))
     (is (= "foo" (json/decode (json/encode thing) true)))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-map {:foo "bar"} jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-map {:foo "bar"} jg)))
     (is (= {:foo "bar"} (json/decode (json/encode thing) true)))
     (remove)
-    (gen/add-encoder CTestR (fn [obj jg] (gen/encode-symbol 'foo jg)))
+    (gen/add-encoder CTestR (fn [_obj jg] (gen/encode-symbol 'foo jg)))
     (is (= "foo" (json/decode (json/encode thing) true)))
     (remove)))
 


=====================================
test/cheshire/test/custom.clj
=====================================
@@ -1,8 +1,10 @@
 (ns cheshire.test.custom
   "DEPRECATED, kept here to ensure backward compatibility."
-  (:use [clojure.test]
-        [clojure.java.io :only [reader]])
-  (:require [cheshire.custom :as json] :reload
+  (:require [clojure.test :refer [deftest is]]
+            [clojure.java.io :as io]
+            [clojure.string :as str]
+            #_{:clj-kondo/ignore [:deprecated-namespace]}
+            [cheshire.custom :as json] :reload
             [cheshire.factory :as fact]
             [cheshire.parse :as parse])
   (:import (java.io StringReader StringWriter
@@ -157,9 +159,9 @@
 
 (deftest test-multiple-objs-in-file
   (is (= {"one" 1, "foo" "bar"}
-         (first (json/parsed-seq (reader "test/multi.json")))))
+         (first (json/parsed-seq (io/reader "test/multi.json")))))
   (is (= {"two" 2, "foo" "bar"}
-         (second (json/parsed-seq (reader "test/multi.json"))))))
+         (second (json/parsed-seq (io/reader "test/multi.json"))))))
 
 (deftest test-jsondotorg-pass1
   (let [string (slurp "test/pass1.json")
@@ -195,12 +197,17 @@
            (type (:foo (json/decode "{\"foo\":NaN}" true)))))))
 
 (deftest t-persistent-queue
-  (let [q (conj (clojure.lang.PersistentQueue/EMPTY) 1 2 3)]
+  (let [q (conj clojure.lang.PersistentQueue/EMPTY 1 2 3)]
     (is (= q (json/decode (json/encode* q))))))
 
 (deftest t-pretty-print
-  (is (= (str "{\n  \"bar\" : [ {\n    \"baz\" : 2\n  }, "
-              "\"quux\", [ 1, 2, 3 ] ],\n  \"foo\" : 1\n}")
+  (is (= (str/join (System/lineSeparator)
+                   ["{"
+                    "  \"bar\" : [ {"
+                    "    \"baz\" : 2"
+                    "  }, \"quux\", [ 1, 2, 3 ] ],"
+                    "  \"foo\" : 1"
+                    "}"])
          (json/encode* (sorted-map :foo 1 :bar [{:baz 2} :quux [1 2 3]])
                        {:pretty true}))))
 
@@ -233,7 +240,7 @@
 (deftest test-shadowing-default-encoder
   (json/remove-encoder java.util.Date)
   (json/add-encoder java.util.Date
-                    (fn [d jg] (json/encode-str "foo" jg)))
+                    (fn [_d jg] (json/encode-str "foo" jg)))
   (is (= "\"foo\"" (json/encode* (java.util.Date.))))
   (is (= "\"foo\"" (json/encode* :foo)))
   (json/remove-encoder java.util.Date)


=====================================
test/cheshire/test/generative.clj
=====================================
@@ -1,19 +1,19 @@
 (ns cheshire.test.generative
-  (:use [cheshire.core]
-        [clojure.test.generative]
-        [clojure.test :only [deftest is]]))
+  (:require [cheshire.core :as json]
+            [clojure.test.generative :refer [defspec] :as g]
+            [clojure.test :refer [deftest is]]))
 
 ;; determines whether generative stuff is printed to stdout
 (def verbose true)
 
 (defn encode-equality [x]
-  [x (decode (encode x))])
+  [x (json/decode (json/encode x))])
 
 (defn encode-equality-keys [x]
-  [x (decode (encode x) true)])
+  [x (json/decode (json/encode x) true)])
 
 (defspec number-json-encoding
-  (fn [a b c] [[a b c] (decode (encode [a b c]))])
+  (fn [a b c] [[a b c] (json/decode (json/encode [a b c]))])
   [^int a ^long b ^double c]
   (is (= (first %) (last %))))
 
@@ -47,9 +47,9 @@
   ;; you have more than 16 CPU cores
   (let [seeds (take 16 (repeatedly #(rand-int 1024)))]
     (when-not verbose
-      (reset! report-fn identity))
+      (reset! g/report-fn identity))
     (println "Seeds:" seeds)
-    (binding [*msec* 25000
-              *seeds* seeds
-              *verbose* false]
-      (doall (map deref (test-namespaces 'cheshire.test.generative))))))
+    (binding [g/*msec* 25000
+              g/*seeds* seeds
+              g/*verbose* false]
+      (doall (map deref (g/test-namespaces 'cheshire.test.generative))))))



View it on GitLab: https://salsa.debian.org/clojure-team/cheshire-clojure/-/commit/6ca48b0d46d11d8aa20d8011cf7671a8c566da52

-- 
View it on GitLab: https://salsa.debian.org/clojure-team/cheshire-clojure/-/commit/6ca48b0d46d11d8aa20d8011cf7671a8c566da52
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20261105/47fa8697/attachment.htm>


More information about the pkg-java-commits mailing list