Created
July 29, 2022 16:55
-
-
Save viesti/403e3a67e2bc1add10cf3365ede510bc to your computer and use it in GitHub Desktop.
Keep the order of keys from a JSON object
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
0% cat bb.edn | |
{:deps {org.flatland/ordered {:mvn/version "1.15.10"} | |
org.clojure/data.json {:mvn/version "2.4.0"}}} | |
0% cat ordered.clj | |
(ns ordered | |
(:require [flatland.ordered.map :as ordered-map] | |
[clojure.data.json :as data-json]) | |
(:import (java.io PushbackReader))) | |
;; Taken from https://github.com/clojure/data.json/blob/master/src/main/clojure/clojure/data/json.clj#L295-L317 | |
;; and modified to use ordered-map, instead of (transient {}) | |
(defn read-object-ordered [^PushbackReader stream options] | |
;; Expects to be called with the head of the stream AFTER the | |
;; opening bracket. | |
(let [key-fn (get options :key-fn) | |
value-fn (get options :value-fn)] | |
(loop [result (ordered-map/ordered-map)] | |
(if-let [key (#'data-json/read-key stream)] | |
(let [key (cond-> key key-fn key-fn) | |
value (#'data-json/-read stream true nil options) | |
r (if value-fn | |
(let [out-value (value-fn key value)] | |
(if-not (= value-fn out-value) | |
(assoc result key out-value) | |
result)) | |
(assoc result key value))] | |
(data-json/codepoint-case (int (#'data-json/next-token stream)) | |
\, (recur r) | |
\} r | |
(throw (Exception. "JSON error (missing entry in object)")))) | |
(let [r result] | |
(if (empty? r) | |
r | |
(throw (Exception. "JSON error empty entry in object is not allowed")))))))) | |
(println (-> (slurp "test.json") (data-json/read-str) keys)) | |
;; Replace clojure.data.json/read-object with a version that maintains JSON object key order via flatland.ordered.map/ordered-map | |
(alter-var-root #'data-json/read-object (constantly read-object-ordered)) | |
(println (-> (slurp "test.json") (data-json/read-str) keys)) | |
0% cat test.json | |
{"1": 1, "2": 2, "3": 3, "4":4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9} | |
0% bb ordered.clj | |
(9 3 4 8 7 5 6 1 2) | |
(1 2 3 4 5 6 7 8 9) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment