chenoi
chenoi

Reputation: 565

Not able to get specific value from Json file using python

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

Answers (5)

Andrey Kostrenko
Andrey Kostrenko

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

buran
buran

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

Serge Ballesta
Serge Ballesta

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

Paritosh Singh
Paritosh Singh

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

Jack Casey
Jack Casey

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

Related Questions