Reputation: 565
I'm having difficulty to get some data from my json file. I'm able to get some of the data but when I want to dig more in details I'm getting error and stuck no where.
Running the script below return an error
AttributeError: 'list' object has no attribute 'get'
I know its a list but I'm not sure how to get the rest of the object list.
Script
ifile=open('source.json', 'r')
ofile=open('extract.json', 'w')
json_decode=json.load(ifile)
myresult=[]
for item in json_decode:
mydict={}
mydict['sID']=item.get('Ls id')
my_dict['dID']=item.get('items').get('Link ID').get('Metric').get('Link Type')
mydict['type']=item.get('Type')
myresult.append(mydict)
myjson=json.dumps(myresult, ofile)
ofile.write(myjson)
ofile.close()
source Json file
[
{
"Ls age": "201",
"items": [
{
"Link ID": "1.1.1.2",
"Link Type": "StubNet",
"Metric": "1",
"Data": "255.255.255.255",
"Priority": "Medium"
},
{
"Link ID": "1.1.1.4",
"Link Type": "P-2-P",
"Metric": "1",
"Data": "192.168.100.34"
},
{
"Link ID": "192.168.100.33",
"Link Type": "StubNet",
"Metric": "1",
"Data": "255.255.255.255",
"Priority": "Medium"
},
{
"Link ID": "1.1.1.1",
"Link Type": "P-2-P",
"Metric": "1",
"Data": "192.168.100.53"
}
],
"Len": "84",
"Ls id": "1.1.1.2",
"Adv rtr": "1.1.1.2",
"Type": "Router",
"Link count": "5"
},
{
"Ls age": "1699",
"seq#": "80008d72",
"items": [
{
"Link ID": "1.1.1.1",
"Link Type": "StubNet",
"Metric": "1",
"Data": "255.255.255.255",
"Priority": "Medium"
},
{
"Link ID": "1.1.1.1",
"Link Type": "StubNet",
"Metric": "12",
"Data": "255.255.255.255",
"Priority": "Medium"
},
{
"Link ID": "1.1.1.3",
"Link Type": "P-2-P",
"Metric": "10",
"Data": "192.168.100.26"
},
{
"Link ID": "192.168.100.25",
"Link Type": "StubNet",
"Metric": "10",
"Data": "255.255.255.255",
"Priority": "Medium"
},
{
"Link ID": "1.1.1.2",
"Link Type": "P-2-P",
"Metric": "10",
"Data": "192.168.100.54"
},
{
"Link ID": "192.168.100.53",
"Link Type": "StubNet",
"Metric": "10",
"Data": "255.255.255.255",
"Priority": "Medium"
}
],
"Len": "96",
"Ls id": "1.1.1.1",
"chksum": "0x16fc",
"Adv rtr": "1.1.1.1",
"Type": "Router",
"Options": "ASBR E",
"Link count": "6"
}
]
Expected to have result as below
[
{
"type": "Router",
"sID": "1.1.1.2",
"dID": "1.1.1.2",
"LinkType":"StubNet",
"Metric":"1"
},
{
"type": "Router",
"sID": "1.1.1.2",
"dID": "1.1.1.4",
"Link Type": "P-2-P",
"Metric": "1"
},
{
"type": "Router",
"sID": "1.1.1.2",
"dID": "192.168.100.33",
"LinkType":"StubNet",
"Metric":"1"
},
{
"type": "Router",
"sID": "1.1.1.2",
"dID":"1.1.1.1",
"Link Type": "P-2-P",
"Metric": "1"
},
{
"type": "Router",
"sID": "1.1.1.1",
"dID": "1.1.1.1",
"LinkType":"StubNet",
"Metric":"1"
},
{
"type": "Router",
"sID": "1.1.1.1",
"dID":"1.1.1.1",
"Link Type": "StubNet",
"Metric": "12"
},
{
"type": "Router",
"sID": "1.1.1.1",
"dID": "1.1.1.3",
"LinkType":"P-2-P",
"Metric":"10"
}
]
Appreciate to advise how could proceed further. I have search around and try error and still no able to resolve it. Appreciate your advise and support. Thank you
Upvotes: 2
Views: 504
Reputation: 119
to process the elements of a nested object of the list, you need to use an additional loop, for example,
import json
ifile = 'source.json'
ofile = 'extract.json'
myresult = []
with open(ifile, 'r') as sf:
json_decode = json.load(sf)
for item in json_decode:
for sub_item in item.get('items', []):
myresult.append(dict(type=item.get('Type'),
sID=item.get('Ls id', ''),
dID=sub_item.get('Link ID'),
LinkType=sub_item.get('Link Type'),
Metric=sub_item.get('Metric')
)
)
with open(ofile, 'w') as of:
of.write(json.dumps(myresult, indent=4))
or a slightly abbreviated version using list comprehension:
import json
ifile = 'source.json'
ofile = 'extract.json'
with open(ifile, 'r') as sf:
json_decode = json.load(sf)
myresult = [dict(type=item.get('Type'),
sID=item.get('Ls id', ''),
dID=sub_item.get('Link ID'),
LinkType=sub_item.get('Link Type'),
Metric=sub_item.get('Metric')) for item in json_decode
for sub_item in item.get('items', [])]
with open(ofile, 'w') as of:
of.write(json.dumps(myresult, indent=4))
Upvotes: 1
Reputation: 14233
you need to iterate over devices and then over device['items']
import json
with open('source.json', 'r') as ifile:
json_data=json.load(ifile)
my_result=[]
for device in json_data:
for item in device.get('items', []):
my_dict={}
my_dict['type'] = device.get('Type')
my_dict['sID'] = device.get('Ls id')
my_dict['dID'] = item.get('Link ID')
my_dict['Link Type'] = item.get('Link Type')
my_dict['Metric'] = item.get('Metric')
my_result.append(my_dict)
with open('extract.json', 'w') as ofile:
json.dump(my_result, ofile, indent=4)
For more structured code you may want to define a function(s) that takes device/item as argument, parse it and return a list of dicts/dict
Upvotes: 1
Reputation: 148880
The problem is that item['items']
is also a list so you need an inner loop to process all of its elements. Furthermore you must extract individually each value:
for item in json_decode:
for sub in item.get('items'):
mydict={}
mydict['type']=item.get('Type')
mydict['sID']=item.get('Ls id')
mydict['dID']=sub.get('Link ID')
mydict['Link Type']=sub.get('Link Type')
mydict['Metric']=sub.get('Metric')
myresult.append(mydict)
Upvotes: 1
Reputation: 6246
First, you are getting a list in item['items']
. You need to decide whether you need to save all values available inside that list or not.
Second, you are trying to access multiple attributes in a dict at once, but you're chaining the get
commands. The code however attempts to treat it like a nested dict, and would run into datatype errors.
Third, you don't actually need to type get
like that, a cleaner version is to just use the square bracket notation.
Assuming you need to create a new dict for each of the items in the list of item['items']
a solution would look something like this:
import json
s = '''
[
{
"Ls age": "201",
"items": [
{
"Link ID": "1.1.1.2",
"Link Type": "StubNet",
"Metric": "1",
"Data": "255.255.255.255",
"Priority": "Medium"
},
{
"Link ID": "1.1.1.4",
"Link Type": "P-2-P",
"Metric": "1",
"Data": "192.168.100.34"
},
{
"Link ID": "192.168.100.33",
"Link Type": "StubNet",
"Metric": "1",
"Data": "255.255.255.255",
"Priority": "Medium"
},
{
"Link ID": "1.1.1.1",
"Link Type": "P-2-P",
"Metric": "1",
"Data": "192.168.100.53"
}
],
"Len": "84",
"Ls id": "1.1.1.2",
"Adv rtr": "1.1.1.2",
"Type": "Router",
"Link count": "5"
},
{
"Ls age": "1699",
"seq#": "80008d72",
"items": [
{
"Link ID": "1.1.1.1",
"Link Type": "StubNet",
"Metric": "1",
"Data": "255.255.255.255",
"Priority": "Medium"
},
{
"Link ID": "1.1.1.1",
"Link Type": "StubNet",
"Metric": "12",
"Data": "255.255.255.255",
"Priority": "Medium"
},
{
"Link ID": "1.1.1.3",
"Link Type": "P-2-P",
"Metric": "10",
"Data": "192.168.100.26"
},
{
"Link ID": "192.168.100.25",
"Link Type": "StubNet",
"Metric": "10",
"Data": "255.255.255.255",
"Priority": "Medium"
},
{
"Link ID": "1.1.1.2",
"Link Type": "P-2-P",
"Metric": "10",
"Data": "192.168.100.54"
},
{
"Link ID": "192.168.100.53",
"Link Type": "StubNet",
"Metric": "10",
"Data": "255.255.255.255",
"Priority": "Medium"
}
],
"Len": "96",
"Ls id": "1.1.1.1",
"chksum": "0x16fc",
"Adv rtr": "1.1.1.1",
"Type": "Router",
"Options": "ASBR E",
"Link count": "6"
}
]
'''
input_lst = json.loads(s)
myresult=[]
for item in input_lst:
mydict={}
mydict_sID = item['Ls id']
mydict_type = item['Type']
temp = []
for x in item['items']:
mydict={'Ls id': mydict_sID,
'Type': mydict_type,
'Link ID': x['Link ID'],
'Metric': x['Metric'],
'Link Type': x['Link Type']
}
temp.append(mydict)
myresult.extend(temp)
Make sure you change the code lines that i used to read the string as necessary.
Upvotes: 1
Reputation: 1836
You should be able to access the values like a dictionary, for example:
ifile=open('source.json', 'r')
ofile=open('extract.json', 'w')
json_decode=json.load(ifile)
myresult=[]
for item in json_decode:
mydict={}
mydict['sID']=item['Ls id']
my_dict['dID']=item['items']['Link ID']['Metric']['Link Type']
mydict['type']=item['Type']
myresult.append(mydict)
myjson=json.dumps(myresult, ofile)
ofile.write(myjson)
ofile.close()
Does this work for you? If not, what errors are you running into?
Upvotes: 1