title: Python: Write Nested JSON as multiple elements in List
body: <p>after two almost three days of programming, I am seeking for help.</p>
  
  <p>What I want to do: Import Json string/ file and write it to a database. There are multiple combination of the input (cars). To lowest nested dict/ list defines the number of elements of a list which will be written in the DB.</p>
  
  <p>Here is the JSON/ String:</p>
  
  <pre><code>input = [{"id":"BMW_1_Series",
          "years":[{"id":10052,"year":2008,
                      "styles":[{"id":560,"name":"128i 2",
                                 "submodel":{"body":"Conver","niceName":"conve"},"trim":"128i"},
                                {"id":561,"name":"135i ",
                                 "submodel":{"body":"Conver","niceName":"conver"},"trim":"135i"}
                                ]
                    },
                   {"id":427,"year":2016,
                    "styles":[{"id":433,"name":"228i ",
                               "submodel":{"body":"Conve", "niceName":"conver"},"trim":"228i SULEV"},
                              {"id":431,"name":"M235i",
                               "submodel":{"body":"Coupe", "niceName":"m235i"},"trim":"M235i"}
                              ]
                    }
                   ]
            }
           #I deleted the other entries, but it is a list
           ]
  </code></pre>
  
  <p>The output should be a dict and the keys for a subdict should be a prefix for the sub-key:</p>
  
  <pre><code>{'id': 427, 'year': 2016, 'styles_id': 431, 'styles_name': 'M235i',   'styles_trim': 'M235i', 'submodel_body': 'Coupe', 'submodel_niceName': 'm235i'}
  </code></pre>
  
  <p>I got it to work from years onwards:</p>
  
  <pre><code>for s in years:#styles
      outputA ={}
      for specifierA, valueA in s.items():
          if isinstance(valueA, list):
              for A in valueA:
                  if isinstance(A, dict):
                      outputB = {}
                      for specifierB, valueB in A.items(): #submodel
                          if isinstance(valueB, dict):
                              for specifierBB, valueBB in valueB.items():
                                  outputA[specifierB+"__"+specifierBB]= valueBB
                          else:
                              outputA[specifierA+"_"+specifierB]= valueB
                  else:
                      outputA[specifierA] = valueA
  
          elif isinstance(valueA, dict):
              outputB = {}
              for specifierB, valueB in valueA.items(): #submodel
                  outputA[specifierA+"_"+specifierB]= valueB
          else:
              outputA[specifierA] = valueA
      print(str(outputA))
      output.append(outputA)
  </code></pre>
  
  <p>I stoped here as I wanted to have a general case on how to read JSON files containing dicts, list and normal values.</p>
  
  <p>My approach for that so far (it is not working and I spent three days on it... (I delted all the intermediate prints for easier reading) *Note: COde is a continuous loop...</p>
  
  <pre><code>def readL(input, prefix=""):
      x = True
      output={}
      k=0
      while (x):
          k+=1
          x=False
          if isinstance(input, list):
              print("LIST: "+str(input))
              for A in input:
                  if isinstance(A, dict):
                      output = dict(output, **readL(A))
                  elif isinstance(A, list):
                      output = dict(output, **readL(A))
          elif isinstance(input, dict):           
              for specifierB, valueB in input.items(): #submodel
                  if isinstance(valueB, dict):
                      specifierB = str(specifierB)+"_"
                      output = dict(output, **readL(valueB,specifierB))
                  if isinstance(valueB, list):
                      specifierB = str(specifierB)+"_"
                      output = dict(output, **readL(valueB,specifierB))  
                  spec =  prefix+specifierB                
                  output[spec] = valueB  
  
  #check if Output Dict contains list or Dict -&gt; continue loop
          for specifierT, valueT in output.items():
              if isinstance(valueT, dict) or isinstance(valueT, list):
                  x = True
          if k ==1:# I have a continues loop so far, thats why
              break
      return(output)
  
  readL(test)
  </code></pre>
  
  <p>Basically, I want to have a recursive function that continuesly calls itself until no dict/ list is in the output anymore.</p>
  
  <p>I am also open to any other faster methods on how to read the input.</p>
  
  <p>I am very desperately looking forward for some advice. Please bear with me, i am pretty new to Python.</p>
  
  <p>THANKS A LOT!</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I found a partial solution at <a href="https://stackoverflow.com/questions/21512957/flattening-generic-json-list-of-dicts-or-lists-in-python">Flattening Generic JSON List of Dicts or Lists in Python</a> from @poke</p>
  
  <pre><code>def splitObj (obj, prefix = None):
      '''
      Split the object, returning a 3-tuple with the flat object, optionally
      followed by the key for the subobjects and a list of those subobjects.
      '''
      # copy the object, optionally add the prefix before each key
      new = obj.copy() if prefix is None else { '{}_{}'.format(prefix, k): v for k, v in obj.items() }
  
      # try to find the key holding the subobject or a list of subobjects
      for k, v in new.items():
          # list of subobjects
          if isinstance(v, list):
              del new[k]
              return new, k, v
          # or just one subobject
          elif isinstance(v, dict):
              del new[k]
              return new, k, [v]
      return new, None, None
  
  def flatten (data, prefix = None):
      '''
      Flatten the data, optionally with each key prefixed.
      '''
      # iterate all items
      for item in data:
          # split the object
          flat, key, subs = splitObj(item, prefix)
  
          # just return fully flat objects
          if key is None:
              yield flat
              continue
  
          # otherwise recursively flatten the subobjects
          for sub in flatten(subs, key):
              sub.update(flat)
              yield sub
  </code></pre>
  
  <p>But as my input has changed as well a bit:</p>
  
  <pre><code>input = [{'states': ['USED'], 'niceName': '1-series', 'id': 'BMW_1_Series',
              'years': [{'styles':
                         [{'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'},
                           'name': '128i 2dr Convertible (3.0L 6cyl 6M)', 'id': 100994560},
                          {'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'},
                            'name': '128i 2dr Coupe (3.0L 6cyl 6M)', 'id': 100974974},
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '135i 2dr Coupe (3.0L 6cyl Turbo 6M)', 'id': 100974975},
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '135i 2dr Convertible (3.0L 6cyl Turbo 6M)', 'id': 100994561}
                          ],
                         'states': ['USED'], 'id': 100524709, 'year': 2008},
                        {'styles':
                         [{'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '135i 2dr Coupe (3.0L 6cyl Turbo 6M)', 'id': 101082656}, 
                          {'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '128i 2dr Coupe (3.0L 6cyl 6M)', 'id': 101082655},
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '135i 2dr Convertible (3.0L 6cyl Turbo 6M)', 'id': 101082663},
                          {'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '128i 2dr Convertible (3.0L 6cyl 6M)', 'id': 101082662}
                          ], 
                         'states': ['USED'], 'id': 100503222, 'year': 2009},
                        {'styles': 
                         [{'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '128i 2dr Coupe (3.0L 6cyl 6M)', 'id': 101200599},
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '135i 2dr Coupe (3.0L 6cyl Turbo 6M)', 'id': 101200600}, 
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '135i 2dr Convertible (3.0L 6cyl Turbo 6M)', 'id': 101200607}, 
                          {'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '128i 2dr Convertible (3.0L 6cyl 6M)', 'id': 101200601}
                          ], 
                         'states': ['USED'], 'id': 100529091, 'year': 2010}, 
                        {'styles':
                         [{'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '128i 2dr Coupe (3.0L 6cyl 6M)', 'id': 101288165}, 
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '135i 2dr Coupe (3.0L 6cyl Turbo 6M)', 'id': 101288166}, 
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '135i 2dr Convertible (3.0L 6cyl Turbo 6M)', 'id': 101288298}, 
                          {'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '128i 2dr Convertible (3.0L 6cyl 6M)', 'id': 101288297}
                          ], 
                         'states': ['USED'], 'id': 100531309, 'year': 2011}, 
                        {'styles': 
                         [{'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '128i 2dr Convertible (3.0L 6cyl 6M)', 'id': 101381667}, 
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '135i 2dr Convertible (3.0L 6cyl Turbo 6M)', 'id': 101381668}, 
                          {'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '128i 2dr Coupe (3.0L 6cyl 6M)', 'id': 101381665}, 
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '135i 2dr Coupe (3.0L 6cyl Turbo 6M)', 'id': 101381666}
                          ], 
                         'states': ['USED'], 'id': 100534729, 'year': 2012}, 
                        {'styles': 
                         [{'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                          'name': '128i 2dr Coupe (3.0L 6cyl 6M)', 'id': 200428722},
                          {'trim': '128i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '128i 2dr Convertible (3.0L 6cyl 6M)', 'id': 200428721}, 
                          {'trim': '135is', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '135is 2dr Coupe (3.0L 6cyl Turbo 6M)', 'id': 200421701}, 
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '135i 2dr Coupe (3.0L 6cyl Turbo 6M)', 'id': 200428724}, 
                          {'trim': '135i', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '135i 2dr Convertible (3.0L 6cyl Turbo 6M)', 'id': 200428723}, 
                          {'trim': '128i SULEV', 'states': ['USED'], 'submodel': {'body': 'Coupe', 'niceName': 'coupe', 'modelName': '1 Series Coupe'}, 
                           'name': '128i SULEV 2dr Coupe (3.0L 6cyl 6M)', 'id': 200428726}, 
                          {'trim': '128i SULEV', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '128i SULEV 2dr Convertible (3.0L 6cyl 6M)', 'id': 200428725}, 
                          {'trim': '135is', 'states': ['USED'], 'submodel': {'body': 'Convertible', 'niceName': 'convertible', 'modelName': '1 Series Convertible'}, 
                           'name': '135is 2dr Convertible (3.0L 6cyl Turbo 6M)', 'id': 200428727}
                          ], 
                         'states': ['USED'], 'id': 200421700, 'year': 2013}
                        ], 
            'name': '1 Series', 'make': {'niceName': 'bmw', 'name': 'BMW', 'id': 200000081}
            }]
  </code></pre>
  
  <p>But I receive the error:</p>
  
  <pre><code>AttributeError: 'str' object has no attribute 'update'
  </code></pre>
  
  <p>as it is not handling <code>'states': ['USED']</code> i think</p>
  
  <p>What can I do about it?</p>
  
  <p>I moved this problem to <a href="https://stackoverflow.com/questions/36731480/flatten-nested-json-dict-list-into-list-to-prepare-to-write-into-db-python">Flatten nested JSON (Dict, List) into List to prepare to write into DB</a>
  Please comment there. Thanks!</p>