Compact but pretty JSON output in python?
Asked Answered
D

3

15

JSON is written either with indent=None (default) as a single line (unreadable to a human eye) or with ident=N with a newline after each comma.

What I would like to see is a more compact but still pretty output, similar to what Common Lisp pretty-printing does. E.g., instead of

 {
  "cleanup":{
   "cpu":6936.780000000001,
   "wall":7822.319401979446
  },
  "finished":"2017-08-14 18:36:23",
  "init":{
   "cpu":1365.73,
   "wall":1380.7802910804749
  },
  "job":"timings",
  "run":{
   "cpu":953.6700000000001,
   "wall":8350.496850013733
  },
  "started":"2017-08-14 13:28:06"
 }

I would like to see

 {
  "cleanup":{"cpu":6936.780000000001,"wall":7822.319401979446},
  "finished":"2017-08-14 18:36:23",
  "init":{"cpu":1365.73,"wall":1380.7802910804749},
  "job":"timings",
  "run":{"cpu":953.6700000000001,"wall":8350.496850013733},
  "started":"2017-08-14 13:28:06"
 }

similar to what pprint produces.

Dulosis answered 14/8, 2017 at 19:27 Comment(7)
compact=True might get you half-way there...Chaschase
English description: "if an object/array contains no objects/arrays as children, format it as a single line; else format it as multiple indented lines"Turret
@juanpa.arrivillaga: the standard json module does not support compact=True.Dulosis
@o11c: this is a good start, although, if there are too many components, some newlines+indent can be inserted.Dulosis
@Dulosis sorry, that was for pprintChaschase
@juanpa.arrivillaga: I use python2Dulosis
Modify the two if _indent is None lines in _make_iterencode in the json.encoder module, then replace JSONEncoder.iterencode in a subclass. Lots of copypasta though :(Turret
B
3

This won't get it quite as tight as you want, but it is the format I find most satisfying. You can test it online at https://beautifier.io/

pip install jsbeautifier

To use:

import jsbeautifier
print( jsbeautifier.beautify(json.dumps(data)) )

See https://www.npmjs.com/package/js-beautify for help with formatting options and so on.

Binnacle answered 24/4, 2022 at 11:29 Comment(0)
D
2

This is not possible at this time, but when RFE: more compact pretty printing is implemented, this question will be answered by using python-rapidjson.

Dulosis answered 1/8, 2018 at 18:42 Comment(0)
C
2

I don't know of a tool that already does this, but it isn't hard to make one:

def compact(d):
    def tight(obj):
        return dumps(obj, separators=(',', ':'))
    print('{')
    for i, (k, v) in enumerate(d.items()):
        comma = ',' if i < len(d) else ''
        print(f' {tight(k)}:{tight(v)}{comma}')
    print('}')

For your example, this emits:

>>> compact(d)
{
 "cleanup":{"cpu":6936.780000000001,"wall":7822.319401979446},
 "finished":"2017-08-14 18:36:23",
 "init":{"cpu":1365.73,"wall":1380.7802910804749},
 "job":"timings",
 "run":{"cpu":953.6700000000001,"wall":8350.496850013733},
 "started":"2017-08-14 13:28:06",
}
Committeeman answered 27/1, 2020 at 8:6 Comment(3)
This does not handle deeper nesting and more complex structures.Dulosis
@Dulosis Adding a little recursion isn't hard to do. The purpose of an answer is to point the way. It is not the job of respondent to write a production tool that meets all desires for all possible users. In this case, it produces exactly what the OP asked for and it easy to understand.Committeeman
What will be the library for dumps?Junk

© 2022 - 2024 — McMap. All rights reserved.