Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pretty print json but keep inner arrays on one line python

I am pretty printing a json in Python using this code:

json.dumps(json_output, indent=2, separators=(',', ': ') 

This prints my json like:

{         "rows_parsed": [         [           "a",           "b",           "c",           "d"         ],         [           "e",           "f",           "g",           "i"         ],     ] } 

However, I want it to print like:

{         "rows_parsed": [         ["a","b","c","d"],         ["e","f","g","i"],     ] } 

How can I keep the arrays that are in arrays all on one line like above?

like image 655
Ben Sandler Avatar asked Oct 08 '14 19:10

Ben Sandler


People also ask

How do you write JSON format in Python?

Method 2: Writing JSON to a file in Python using json.dump() Another way of writing JSON to a file is by using json. dump() method The JSON package has the “dump” function which directly writes the dictionary to a file in the form of JSON, without needing to convert it into an actual JSON object.

How do you print your response in JSON format?

print(response. json()) should give the the data formatted as JSON for this response.


2 Answers

Here is a way to do it with as least amount of modifications as possible:

import json from json import JSONEncoder import re  class MarkedList:     _list = None     def __init__(self, l):         self._list = l  z = {         "rows_parsed": [         MarkedList([           "a",           "b",           "c",           "d"         ]),         MarkedList([           "e",           "f",           "g",           "i"         ]),     ] }  class CustomJSONEncoder(JSONEncoder):     def default(self, o):         if isinstance(o, MarkedList):             return "##<{}>##".format(o._list)  b = json.dumps(z, indent=2, separators=(',', ':'), cls=CustomJSONEncoder) b = b.replace('"##<', "").replace('>##"', "")  print(b) 

Basically the lists that you want formatted in that way you make instance of MarkedList and they get parsed as strings with hopefully unique enough sequence that is later stripped from the output of dumps. This is done to eliminate the quotes that are put around a json string.

Another much more efficient way to do it, but a much more ugly one is to monkey patch json.encoder._make_iterencode._iterencode with something like:

def _iterencode(o, _current_indent_level):     if isinstance(o, str):         yield _encoder(o)     elif o is None:         yield 'null'     elif o is True:         yield 'true'     elif o is False:         yield 'false'     elif isinstance(o, int):         # see comment for int/float in _make_iterencode         yield _intstr(o)     elif isinstance(o, float):         # see comment for int/float in _make_iterencode         yield _floatstr(o)     elif isinstance(o, MarkedList):         yield _my_custom_parsing(o)     elif isinstance(o, (list, tuple)):         yield from _iterencode_list(o, _current_indent_level)     elif isinstance(o, dict):         yield from _iterencode_dict(o, _current_indent_level)     else:         if markers is not None:             markerid = id(o)             if markerid in markers:                 raise ValueError("Circular reference detected")             markers[markerid] = o         o = _default(o)         yield from _iterencode(o, _current_indent_level)         if markers is not None:             del markers[markerid] 
like image 153
Martin Gergov Avatar answered Sep 17 '22 06:09

Martin Gergov


I don't see how you could do it in the json.dumps. After a bit of searching I came across a few options: One option would be to do some post-processing with a custom function:

def fix_json_indent(text, indent=3):             space_indent = indent * 4     initial = " " * space_indent     json_output = []     current_level_elems = []     all_entries_at_level = None  # holder for consecutive entries at exact space_indent level     for line in text.splitlines():         if line.startswith(initial):             if line[space_indent] == " ":                 # line indented further than the level                 if all_entries_at_level:                     current_level_elems.append(all_entries_at_level)                     all_entries_at_level = None                 item = line.strip()                 current_level_elems.append(item)                 if item.endswith(","):                     current_level_elems.append(" ")             elif current_level_elems:                 # line on the same space_indent level                 # no more sublevel_entries                  current_level_elems.append(line.strip())                 json_output.append("".join(current_level_elems))                 current_level_elems = []             else:                 # line at the exact space_indent level but no items indented further                 if all_entries_at_level:                     # last pending item was not the start of a new sublevel_entries.                     json_output.append(all_entries_at_level)                 all_entries_at_level = line.rstrip()         else:             if all_entries_at_level:                 json_output.append(all_entries_at_level)                 all_entries_at_level = None             if current_level_elems:                 json_output.append("".join(current_level_elems))             json_output.append(line)     return "\n".join(json_output) 

Another possibility is a regex but it is quite ugly and depends on the structure of the code you posted:

def fix_json_indent(text):     import re     return  re.sub('{"', '{\n"', re.sub('\[\[', '[\n[', re.sub('\]\]', ']\n]', re.sub('}', '\n}', text)))) 
like image 20
Oliwia Avatar answered Sep 19 '22 06:09

Oliwia