How to treeify Python dicts?

Question:

I’m building a telegram bot, and would like to convert the json responses such as the one below which I turn into a dictionary:

{
  "message_id": 445793,
  "from": {
   "id": 106596774,
   "is_bot": false,
   "first_name": "Komron",
   "last_name": "Aripov",
   "username": "tgcode",
   "language_code": "en"
  },
  "chat": {
   "id": 106596774,
   "first_name": "Komron",
   "last_name": "Aripov",
   "username": "tgcode",
   "type": "private"
  },
  "date": 1549380586,
  "text": "ayye"
}

into a neat little tree, such as this:

Message
 ├ message_id: 445793
 ├ from
 ┊  ├ id: 106596774
 ┊  ├ is_bot: false
 ┊  ├ first_name: Komron
 ┊  ├ last_name: Aripov
 ┊  ├ username: tgcode
 ┊  └ language_code: en
 ├ chat
 ┊  ├ id: 106596774
 ┊  ├ first_name: Komron
 ┊  ├ last_name: Aripov
 ┊  ├ username: tgcode
 ┊  └ type: private
 ├ date: 1549290736
 └ text: ayye

I’ve tried using the treelib library for python, but it is doesn’t offer a method for their class to convert a json into the needed formatted text. It also seems a little too complex for my use case.

There’s a library for my use case on github, but it’s in javascript (can’t understand it to reverse engineer)

Asked By: Sergey Ronin

||

Answers:

This seemed like fun so I gave it a go:

def custom_display(input, depth = 0):
    if depth == 0:
        output_string = "Messagen"
    else:
        output_string = ""
    if type(input) is dict:
        final_index = len(input)-1
        current_index = 0
        for key, value in input.items():
            for indent in range(0, depth):
                output_string += "  ┊ "
            if current_index == final_index:
                output_string += "  └ "
            else:
                output_string += "  ├ "
                current_index += 1
            if type(value) is dict:
                output_string += key + 'n' + custom_display(value, depth + 1)
            else:
                output_string += key + ": " + custom_display(value, depth+1) + 'n'
    else:
        output_string = str(input)

    return output_string

Using,

dict_input = {
  "message_id": 445793,
  "from": {
   "id": 106596774,
   "is_bot": False,
   "first_name": "Komron",
   "last_name": "Aripov",
   "username": "tgcode",
   "language_code": "en"
  },
  "chat": {
   "id": 106596774,
   "first_name": "Komron",
   "last_name": "Aripov",
   "username": "tgcode",
   "type": "private"
  },
  "date": 1549380586,
  "text": "ayye"
}

print(custom_display(dict_input))

Gives an output of:

Message
  ├ message_id: 445793
  ├ from
  ┊   ├ id: 106596774
  ┊   ├ is_bot: False
  ┊   ├ first_name: Komron
  ┊   ├ last_name: Aripov
  ┊   ├ username: tgcode
  ┊   └ language_code: en
  ├ chat
  ┊   ├ id: 106596774
  ┊   ├ first_name: Komron
  ┊   ├ last_name: Aripov
  ┊   ├ username: tgcode
  ┊   └ type: private
  ├ date: 1549380586
  └ text: ayye
Answered By: Andrew McDowell

Following up to Andrew McDowell’s answer : how would you output lists like this :

Message
  ├ message_id: 445793
  ├ from
  ┊   ├ id: 106596774
  ┊   ├ is_bot: False
  ┊   ├ first_name: Komron
  ┊   ├ last_name: Aripov
  ┊   ├ username: tgcode
  ┊   └ language_code: en
  ├ chat
  ┊   ├ id: 106596774
  ┊   ├ first_name: Komron
  ┊   ├ last_name: Aripov
  ┊   ├ username: tgcode
  ┊   ├ list:
  ┊   ┊   ├ elt1
  ┊   ┊   ├ elt2
  ┊   ┊   ├ elt3
  ┊   ┊   └ elt4
  ┊   └ type: private
  ├ date: 1549380586
  └ list1:
      ├ elt1
      ├ elt2
      ├ elt3
      └ elt4
Answered By: KVN
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.