Python: Write Nested JSON as multiple elements in List -


after 2 3 days of programming, seeking help.

what want do: import json string/ file , write database. there multiple combination of input (cars). lowest nested dict/ list defines number of elements of list written in db.

here json/ string:

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 other entries, list          ] 

the output should dict , keys subdict should prefix sub-key:

{'id': 427, 'year': 2016, 'styles_id': 431, 'styles_name': 'm235i',   'styles_trim': 'm235i', 'submodel_body': 'coupe', 'submodel_nicename': 'm235i'} 

i got work years onwards:

for s in years:#styles     outputa ={}     specifiera, valuea in s.items():         if isinstance(valuea, list):             in valuea:                 if isinstance(a, dict):                     outputb = {}                     specifierb, valueb in a.items(): #submodel                         if isinstance(valueb, dict):                             specifierbb, valuebb in valueb.items():                                 outputa[specifierb+"__"+specifierbb]= valuebb                         else:                             outputa[specifiera+"_"+specifierb]= valueb                 else:                     outputa[specifiera] = valuea          elif isinstance(valuea, dict):             outputb = {}             specifierb, valueb in valuea.items(): #submodel                 outputa[specifiera+"_"+specifierb]= valueb         else:             outputa[specifiera] = valuea     print(str(outputa))     output.append(outputa) 

i stoped here wanted have general case on how read json files containing dicts, list , normal values.

my approach far (it not working , spent 3 days on it... (i delted intermediate prints easier reading) *note: code continuous loop...

def readl(input, prefix=""):     x = true     output={}     k=0     while (x):         k+=1         x=false         if isinstance(input, list):             print("list: "+str(input))             in input:                 if isinstance(a, dict):                     output = dict(output, **readl(a))                 elif isinstance(a, list):                     output = dict(output, **readl(a))         elif isinstance(input, dict):                        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 -> continue loop         specifiert, valuet in output.items():             if isinstance(valuet, dict) or isinstance(valuet, list):                 x = true         if k ==1:# have continues loop far, thats why             break     return(output)  readl(test) 

basically, want have recursive function continuesly calls until no dict/ list in output anymore.

i open other faster methods on how read input.

i desperately looking forward advice. please bear me, pretty new python.

thanks lot!

update

i found partial solution @ flattening generic json list of dicts or lists in python @poke

def splitobj (obj, prefix = none):     '''     split object, returning 3-tuple flat object, optionally     followed key subobjects , list of subobjects.     '''     # copy object, optionally add prefix before each key     new = obj.copy() if prefix none else { '{}_{}'.format(prefix, k): v k, v in obj.items() }      # try find key holding subobject or list of subobjects     k, v in new.items():         # list of subobjects         if isinstance(v, list):             del new[k]             return new, k, v         # or 1 subobject         elif isinstance(v, dict):             del new[k]             return new, k, [v]     return new, none, none  def flatten (data, prefix = none):     '''     flatten data, optionally each key prefixed.     '''     # iterate items     item in data:         # split object         flat, key, subs = splitobj(item, prefix)          # return flat objects         if key none:             yield flat             continue          # otherwise recursively flatten subobjects         sub in flatten(subs, key):             sub.update(flat)             yield sub 

but input has changed bit:

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}           }] 

but receive error:

attributeerror: 'str' object has no attribute 'update' 

as not handling 'states': ['used'] think

what can it?

i moved problem flatten nested json (dict, list) list prepare write db please comment there. thanks!

i don't think it's neatest solution, think want do:

def flatten(something,parent_key=none):      if parent_key==none:         prefix = ""     else:         prefix = parent_key+"_"      if type(something) == type({}):         temp={}         key in something:             temp.update(flatten(something[key],prefix+key))         return temp      elif type(something) == type([]):         temp = {}         index in range(len(something)):             temp.update(flatten(something[index],prefix+str(index)))         return temp      else:         return {parent_key:something} 

then run like:

if __name__=='__main__':   input_list = [{"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 other entries, list          ]      = flatten(input_list)     print(a) 

if can guarantee id in each list can use id in place of index:

temp.update(flatten(something[index],prefix+str(something[index]['id']))) 

Comments

Popular posts from this blog

Ansible - ERROR! the field 'hosts' is required but was not set -

customize file_field button ruby on rails -

SoapUI on windows 10 - high DPI/4K scaling issue -