On 1/21/2023 10:03 AM, Dino wrote:

I have a question that is a bit of a shot in the dark. I have this nice bash utility installed:

$ tree -d unit/
unit/
├── mocks
├── plugins
│   ├── ast
│   ├── editor
│   ├── editor-autosuggest
│   ├── editor-metadata
│   ├── json-schema-validator
│   │   └── test-documents
│   └── validate-semantic
│       ├── 2and3
│       ├── bugs
│       └── oas3
└── standalone
     └── topbar-insert

I just thought that it would be great if there was a Python utility that visualized a similar graph for nested data structures. Of course I am aware of indent (json.dumps()) and pprint, and they are OK options for my need. It's just that the compact, improved visualization would be nice to have. Not so nice that I would go out of my way to build, but nice enough to use an exising package.

It's not clear to me whether you want to display JSON structures or Python objects. However, Python dictionaries are so similar to JSON structures that a dictionary example should be pretty close.

This can actually be a tricky problem because for complicated nesting, it's not that easy to work out how to display the elements. The examples posted in this thread so far have been somewhat obscured by the use of leader lines, etc, so that it's a little hard to discern the simple core of the algorithm.

Below I include code that displays each leaf element on its own indented line, can only display keys and simple leaf values, and does not construct leader lines so as to keep the code easy to read. In this form it can only display Python dictionaries but could be modified for JSON without too much work.

"""Display nested objects as an indented list."""
INDENT = ' ' * 3
DICT = {'a': {'aa':'AA', 'ab':'AB'},
        'b': {'ba': {'baa': 'BAA', 'bab': 'BAB'},
              'bb':'BB'},
        'c': ['CA', 'CB'],
        'd': 'D' }
SIMPLE_TYPES = (int, float, str, bytes)

def unroll(obj, indent = ''):
    if isinstance(obj, dict):
        unroll_dict(obj, indent)
    else:
        """unroll other kinds of objects (not implemented)."""
        print(indent, 'Can only unroll nested dictionaries')

def unroll_dict(dct, indent = ''):
    """Unroll a dictionary whose values can be either simple or
       nested.
    """
    for k, v in dct.items():
        g.es(indent, k)
        new_indent = indent + INDENT
        if type(v) in SIMPLE_TYPES:
            print(new_indent, v)
        else:
            unroll(v, new_indent)
            # print(f'{new_indent}{v}')

unroll(DICT)

Output:
a
    aa
       AA
    ab
       AB
b
    ba
       baa
          BAA
       bab
          BAB
    bb
       BB
c
    Can only unroll nested dictionaries
d
    D

If you change the last else block, you can make use of the object's internal representation (not for JSON, of course). Change the block to read:

            # unroll(v, new_indent)
            print(f'{new_indent}{v}')

This change gives the following output:

a
   {'aa': 'AA', 'ab': 'AB'}
b
   {'ba': {'baa': 'BAA', 'bab': 'BAB'}, 'bb': 'BB'}
c
   ['CA', 'CB']
d
    D


In practice, I would collect the text fragments into a list instead of printing them, then print the joined list at the end.
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to