Welcome! Please see the About page for a little more info on how this works.

0 votes
in data.json by


Formatted json is very handy for human consumption, for example, while debugging or exploring JSON API. data.json offers formatting in a form of {{pprint-json}}. Problem is, {{pprint-json}} is dead slow because it tries to fit everything within some line width limit. In practice it takes 20-100 times more time to use {{pprint-json}} instead of {{write-str}}, up to the point where it just cannot be used in production:

clojure.data.json=> (def data (read-string (slurp "sample.edn")))


clojure.data.json=> (count data)
clojure.data.json=> (time (do (clojure.data.json/write-str data) nil))
"Elapsed time: 219.33 msecs"
clojure.data.json=> (time (do (with-out-str (clojure.data.json/pprint-json data)) nil))
"Elapsed time: 25271.549 msecs"

Proposed enhancement is very simple: indent new keys and array elements, but do not try to fit values into line width limit. For human, JSON formatted this way is still easy consumable, structure is evident. The only downside is that some lines might become very long.

In a patch attached, I modified {{write-array}} and {{write-object}}, added new {{:indent}} option to {{write}}. To print indented json, one can write now: {{(write-str data :indent true)}}

There's some performance penalty, of course, but relatively small:

clojure.data.json=> (time (do (clojure.data.json/write-str data :indent true) nil)) "Elapsed time: 250.18 msecs"

I also fixed small bug: {{(seq m)}} thing in {{write-object}} should be {{(seq x)}}.

2 Answers

0 votes
Reference: https://clojure.atlassian.net/browse/DJSON-18 (reported by tonsky)
0 votes

This patch has been applied (as of at least clojure.data.json 2.4.0), but the :indent boolean option is not documented in the docstring for the write function.

Also, the indent is currently fixed at 2 spaces per depth level. This is a reasonable default, but possibly the :indent option could be expanded to allow customizing the number of spaces per level. :indent true would be equivalent to :indent 2 and :indent false to :indent 0.

I've updated the docstring to add `:indent` for next release. I logged the indent control to https://clojure.atlassian.net/browse/DJSON-60 for future.
Thanks for the quick fix! One other thing (sorry for not mentioning this initially): the docstring for `json/pprint` should be updated to indicate that `:indent` is not supported.
Thanks, fixed.