【问题标题】:Not able to get specific value from Json file using python无法使用 python 从 Json 文件中获取特定值
【发布时间】:2019-10-03 10:11:48
【问题描述】:

我很难从我的 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"
  }
]

预计结果如下

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

感谢您建议如何进一步进行。我四处搜索并尝试错误,但仍然无法解决它。感谢您的建议和支持。谢谢

【问题讨论】:

    标签: python json list extract


    【解决方案1】:

    您应该能够像字典一样访问值,例如:

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

    这对你有用吗?如果没有,您遇到了什么错误?

    【讨论】:

    • 您好先生..谢谢您的回复和帮助...我收到错误 mydict['dID']=item['items']['Link ID']['Metric' ]['Link Type'] TypeError: 列表索引必须是整数,而不是str
    【解决方案2】:

    您需要遍历设备,然后遍历设备['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)
    

    对于更结构化的代码,您可能需要定义一个以设备/项目作为参数的函数,对其进行解析并返回一个字典/字典列表

    【讨论】:

      【解决方案3】:

      首先,您将在item['items'] 中获得一个列表。您需要决定是否需要保存该列表中的所有可用值。

      其次,您尝试一次访问 dict 中的多个属性,但您正在链接 get 命令。然而,该代码试图将其视为嵌套字典,并且会遇到数据类型错误。

      第三,您实际上不需要像那样输入get,更简洁的版本是只使用方括号表示法。

      假设您需要为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)
      

      确保根据需要更改我用来读取字符串的代码行。

      【讨论】:

      • 感谢先生为我提供指导和对代码的更改。再次感谢您。
      【解决方案4】:

      问题在于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)
      

      【讨论】:

        【解决方案5】:

        要处理列表的嵌套对象的元素,需要使用额外的循环,例如,

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

        【讨论】:

        • 谢谢先生。对于我的情况,两者都是一个很好的解决方案,并且确实有效。感谢分享,我很感激。
        猜你喜欢
        • 1970-01-01
        • 2022-01-09
        • 1970-01-01
        • 2021-04-21
        • 2020-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-19
        相关资源
        最近更新 更多