Не удается получить конкретное значение из файла Json с помощью Python - PullRequest
2 голосов
/ 16 мая 2019

У меня проблемы с получением некоторых данных из моего файла json.Я могу получить некоторые данные, но когда я хочу копать более подробно, я получаю сообщение об ошибке и застрял не где.

Запуск сценария ниже возвращает ошибку

AttributeError: 'list' object has no attribute 'get'

Я знаю, что это список, но я не уверен, как получить остальную часть списка объектов.

Сценарий

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

исходный файл Json

[
  {
    "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"
  }
]

Ожидаемый результат как показано нижеУ меня есть поиск вокруг и попробовать ошибку, и все еще не в состоянии решить ее.Ценю ваши советы и поддержку.Спасибо

Ответы [ 5 ]

1 голос
/ 16 мая 2019

для обработки элементов вложенного объекта списка, вам нужно использовать дополнительный цикл, например,

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

или несколько сокращенная версия с использованием списка:

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 голос
/ 16 мая 2019

Проблема в том, что item['items'] также является списком, поэтому вам необходим внутренний цикл для обработки всех его элементов. Кроме того, вы должны извлекать отдельно каждое значение:

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)
1 голос
/ 16 мая 2019

вам нужно выполнить итерации по устройствам, а затем по устройству ['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)

Для более структурированного кода вы можете определить функцию (и), которая принимает устройство / элемент в качестве аргумента, анализэто и вернуть список dicts / dict

1 голос
/ 16 мая 2019

Сначала вы получаете список в item['items'].Вам нужно решить, нужно ли вам сохранять все значения, доступные в этом списке, или нет.

Во-вторых, вы пытаетесь получить доступ к нескольким атрибутам в dict одновременно, но вы объединяете команды get.Однако в коде делается попытка трактовать его как вложенный диктат, и он может столкнуться с ошибками типов данных.

В-третьих, на самом деле вам не нужно вводить get, более чистая версия - просто использовать квадратскобочные обозначения.

Если вам нужно создать новый dict для каждого из элементов в списке item['items'], решение будет выглядеть примерно так:

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)

Убедитесь, что вы изменилистроки кода, которые я использовал для чтения строки при необходимости.

1 голос
/ 16 мая 2019

Вы должны иметь доступ к таким значениям, как словарь, например:

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

Это работает для вас? Если нет, то с какими ошибками вы сталкиваетесь?

...