title: Creating a tree/deeply nested dict from an indented text file in python
body: <p>Basically, I want to iterate through a file and put the contents of each line into a deeply nested dict, the structure of which is defined by the amount of whitespace at the start of each line.</p>
  
  <p>Essentially the aim is to take something like this:</p>
  
  <pre><code>a
      b
          c
      d
          e
  </code></pre>
  
  <p>And turn it into something like this:</p>
  
  <pre><code>{"a":{"b":"c","d":"e"}}
  </code></pre>
  
  <p>Or this:</p>
  
  <pre><code>apple
      colours
          red
          yellow
          green
      type
          granny smith
      price
          0.10
  </code></pre>
  
  <p>into this:</p>
  
  <pre><code>{"apple":{"colours":["red","yellow","green"],"type":"granny smith","price":0.10}
  </code></pre>
  
  <p>So that I can send it to Python's JSON module and make some JSON.</p>
  
  <p>At the moment I'm trying to make a dict and a list in steps like such:</p>
  
  <ol>
  <li><code>{"a":""} ["a"]</code></li>
  <li><code>{"a":"b"} ["a"]</code></li>
  <li><code>{"a":{"b":"c"}} ["a","b"]</code></li>
  <li><code>{"a":{"b":{"c":"d"}}}} ["a","b","c"]</code></li>
  <li><code>{"a":{"b":{"c":"d"},"e":""}} ["a","e"]</code></li>
  <li><code>{"a":{"b":{"c":"d"},"e":"f"}} ["a","e"]</code></li>
  <li><code>{"a":{"b":{"c":"d"},"e":{"f":"g"}}} ["a","e","f"]</code></li>
  </ol>
  
  <p>etc.</p>
  
  <p>The list acts like 'breadcrumbs' showing where I last put in a dict.</p>
  
  <p>To do this I need a way to iterate through the list and generate something like <code>dict["a"]["e"]["f"]</code> to get at that last dict. I've had a look at the AutoVivification class that someone has made which looks very useful however I'm really unsure of:</p>
  
  <ol>
  <li>Whether I'm using the right data structure for this (I'm planning to send it to the JSON library to create a JSON object)</li>
  <li>How to use AutoVivification in this instance</li>
  <li>Whether there's a better way in general to approach this problem.</li>
  </ol>
  
  <p>I came up with the following function but it doesn't work:</p>
  
  <pre><code>def get_nested(dict,array,i):
  if i != None:
      i += 1
      if array[i] in dict:
          return get_nested(dict[array[i]],array)
      else:
          return dict
  else:
      i = 0
      return get_nested(dict[array[i]],array)
  </code></pre>
  
  <p>Would appreciate help!</p>
  
  <p>(The rest of my extremely incomplete code is here:)</p>
  
  <pre><code>#Import relevant libraries
  import codecs
  import sys
  
  #Functions
  def stripped(str):
      if tab_spaced:
          return str.lstrip('\t').rstrip('\n\r')
      else:
          return str.lstrip().rstrip('\n\r')
  
  def current_ws():
      if whitespacing == 0 or not tab_spaced:
          return len(line) - len(line.lstrip())
      if tab_spaced:
          return len(line) - len(line.lstrip('\t\n\r'))
  
  def get_nested(adict,anarray,i):
      if i != None:
          i += 1
          if anarray[i] in adict:
              return get_nested(adict[anarray[i]],anarray)
          else:
              return adict
      else:
          i = 0
          return get_nested(adict[anarray[i]],anarray)
  
  #initialise variables
  jsondict = {}
  unclosed_tags = []
  debug = []
  
  vividfilename = 'simple.vivid'
  # vividfilename = sys.argv[1]
  if len(sys.argv)&gt;2:
      jsfilename = sys.argv[2]
  else:
      jsfilename = vividfilename.split('.')[0] + '.json'
  
  whitespacing = 0
  whitespace_array = [0,0]
  tab_spaced = False
  
  #open the file
  with codecs.open(vividfilename,'rU', "utf-8-sig") as vividfile:
      for line in vividfile:
          #work out how many whitespaces at start
          whitespace_array.append(current_ws())
  
          #For first line with whitespace, work out the whitespacing (eg tab vs 4-space)
          if whitespacing == 0 and whitespace_array[-1] &gt; 0:
              whitespacing = whitespace_array[-1]
              if line[0] == '\t':
                  tab_spaced = True
  
          #strip out whitespace at start and end
          stripped_line = stripped(line)
  
          if whitespace_array[-1] == 0:
              jsondict[stripped_line] = ""
              unclosed_tags.append(stripped_line)
  
          if whitespace_array[-2] &lt; whitespace_array[-1]:
              oldnested = get_nested(jsondict,whitespace_array,None)
              print oldnested
              # jsondict.pop(unclosed_tags[-1])
              # jsondict[unclosed_tags[-1]]={stripped_line:""}
              # unclosed_tags.append(stripped_line)
  
          print jsondict
          print unclosed_tags
  
  print jsondict
  print unclosed_tags
  </code></pre>