如何将 JSON 字典对象抓取到 pandas 数据框中,而不管字典中是否缺少值?

How to crawl JSON dictionary object into pandas dataframe regardless if value missing in dictionary?

我正在拨打 API 电话并获取我的 JSON 数据,如下所示:

import requests 
import jmespath
import pandas as pd
import json

url = 'a.com'

r = requests.get(url).json()

返回的对象如下所示:

{'question': [{
   'response': {'firstname': {'value': 'John'},
    'lastname': {'value': 'Bob'}},
   'profile_question': [{
     'identities': [{'type': 'ID,
       'value': '1'},
      {'type': 'EMAIL',
       'value': 'test@test.com'}]}]}]}

我尝试将其放入 json.fr,但出现错误,提示格式不正确 json。我如何按原样抓取这个对象,但没有成功满足我的需要。

我正在尝试使用 jmespath 库进行抓取,并想像这样提取四条信息 firstname, lastname, ID, EMAIL 并将数据附加到列表中:

    lst =[]

    fname = jmespath.search('question[*].response.{firstname:firstname.value}',my_dict)
    lst.append(fname)

    lname = jmespath.search('question[*].response.{lastname:lastname.value}',my_dict)
    lst.append(lname)

    email_path = jmespath.search("question[*].profile_question[].identities.{email:[?type=='EMAIL'].value}",my_dict)
    lst.append(email)

    ID = jmespath.search("question[*].profile_question[].identities.{email:[?type=='ID'].value}",my_dict)
    lst.append(ID)

我追加到一个列表中,希望每次迭代都创建可以推入数据框的元组。

列表如下所示:

[[{'firstname': 'John'}],
 [{'lastname': 'Bob'}],
 [{'email': ['test@test.com']}],
 [{'ID': ['1']}]]

然而,当我像这样使用缺失值来抓取字典时:

{'question': [{
   'response': {'firstname': {'value': 'John'},
    'lastname': {'value': 'Bob'}},
   'profile-question': [{
     'identities': [{'type': 'ID,
       'value': '1'},
      {'type': 'EMAIL',
       'value': 'test@test.com'}]}]}],
   'response': {'firstname': {'value': 'John1'},
    'lastname': {'value': 'Bob1'}},
   'profile-question': [{
     'identities': [{'type': 'ID,
       'value': '2'}]}]}

导致我的列表表现得像这样(我不知道为什么):

[[{'firstname': 'John'}], [{'email': ['test@test.com']}], [{'email': ['1']},[{'firstname': 'John'}],
 [{'lastname': 'Bob'}],
 [{'email': [][][]}],
 [{'ID': ['1']}]]]

这导致 df 看起来像这样:

firstname         lastname      email                ID
john                 bob        test@test.com        1 
john1                bob1       test@test.com        1

我如何抓取来自 API 的 JSON dict 对象,提取四条数据 firstname, lastname, email, ID 并像这样附加到数据框中? :

firstname         lastname      email                    ID
    john                 bob        test@test.com        1 
    john1                bob1                            2

非常愿意离开 jmespath 库,补充一点,上面的词典有更多的字段,我已经缩短了,所以只列出了关键点和它们的缩进。

首先,错误的原因是 json 对象在 ID 后缺少引号。

 {'question': [{
   'response': {'firstname': {'value': 'John'},
    'lastname': {'value': 'Bob'}},
   'profile_question': [{
     'identities': [{'type': 'ID,
       'value': '1'},
      {'type': 'EMAIL',
       'value': 'test@test.com'}]}]}]}

它应该是这样的:

{'question': [{
   'response': {'firstname': {'value': 'John'},
    'lastname': {'value': 'Bob'}},
   'profile_question': [{
     'identities': [{'type': 'ID',
       'value': '1'},
      {'type': 'EMAIL',
       'value': 'test@test.com'}]}]}]}

从这里您可以使用 json 库将 json 对象转换为带有 json.loads() 的 python 字典对象。修复 json 对象后,您的代码可能如下所示。

import jmespath as jp
import pandas as pd


jon = {'question':
              [{'response': {'firstname': {'value': 'John'},
                             'lastname': {'value': 'Bob'}},
                'profile_question': [{'identities': [{'type': 'ID',
                                                      'value': '1'},
                                                     {'type': 'EMAIL', 'value': 'test@test.com'}]}]}]}


jsons = [jon] # list of all json objects
df_list = []
for json in jsons:
    try:
        fname = jp.search('question[*].response.firstname.value', jon)[0]
    except IndexError:
        fname = None
    try:
        lname = jp.search('question[*].response.lastname.value', jon)[0]
    except IndexError:
        lname = None
    try:
        email = jp.search("question[*].profile_question[].identities.{email:[?type=='EMAIL'].value}", jon)[0]['email'][0]
    except IndexError:
        email = None
    try:
        user_id = jp.search("question[*].profile_question[].identities.{email:[?type=='ID'].value}", jon)[0]['email'][0]
    except IndexError:
        user_id = None
    df_list.append(pd.DataFrame({'firstname': fname, 'lastname': lname, 'email': email, 'id': user_id}, index=[0]))


df = pd.concat(df_list, ignore_index=True, sort=False)
print(df)