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
Post a Comment