JSON dumps custom formatting
dictionary, json, python
Solution
I have used the example provided by Tim Ludwinski and adapted it to my preference:
class CompactJSONEncoder(json.JSONEncoder):
"""A JSON Encoder that puts small lists on single lines."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.indentation_level = 0
def encode(self, o):
"""Encode JSON object *o* with respect to single line lists."""
if isinstance(o, (list, tuple)):
if self._is_single_line_list(o):
return "[" + ", ".join(json.dumps(el) for el in o) + "]"
else:
self.indentation_level += 1
output = [self.indent_str + self.encode(el) for el in o]
self.indentation_level -= 1
return "[\n" + ",\n".join(output) + "\n" + self.indent_str + "]"
elif isinstance(o, dict):
self.indentation_level += 1
output = [self.indent_str + f"{json.dumps(k)}: {self.encode(v)}" for k, v in o.items()]
self.indentation_level -= 1
return "{\n" + ",\n".join(output) + "\n" + self.indent_str + "}"
else:
return json.dumps(o)
def _is_single_line_list(self, o):
if isinstance(o, (list, tuple)):
return not any(isinstance(el, (list, tuple, dict)) for el in o)\
and len(o) <= 2\
and len(str(o)) - 2 <= 60
@property
def indent_str(self) -> str:
return " " * self.indentation_level * self.indent
def iterencode(self, o, **kwargs):
"""Required to also work with `json.dump`."""
return self.encode(o)
Also see the version I have in use.
Problem
I'd like to dump a Python dictionary into a JSON file with a particular custom format. For example, the following dictionary `my_dict`, ``` 'text_lines': [{"line1"}, {"line2"}] ``` dumped with ``` f.write(json.dumps(my_dict, sort_keys=True, indent=2)) ``` looks like this ``` "text_lines": [ { "line1" }, { "line2" } ] ``` while I prefer that it looks like this ``` "text_lines": [ {"line1"}, {"line2"} ] ``` Similarly, I want the following ``` "location": [ 22, -8 ] ``` to look like this ``` "location": [22, -8] ``` (that is, more like a coordinate, which it is). I know that this is a cosmetic issue, but it's important to me to preserve this formatting for easier hand editing of the file. Any way of doing this kind of customisation? An explained example would be great (the docs did not get me very far).