Search code examples
pythondictionarytree

How to treeify Python dicts?


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)


Solution

  • This seemed like fun so I gave it a go:

    def custom_display(input, depth = 0):
        if depth == 0:
            output_string = "Message\n"
        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