2

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

5 Answers 5

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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?

1 Comment

Hi sir..thank you for your response and help... I'm getting error mydict['dID']=item['items']['Link ID']['Metric']['Link Type'] TypeError: list indices must be integers, not str
1

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.

1 Comment

Thank you sir for provide my the guideline and changes to the code. Thank you again.
1

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)

Comments

1

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))

1 Comment

Thank you sir. Both is a good solution for my case and it does work. Thanks for sharing and i appreciate this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.