在python中替换JSON键值和分解值

2024-10-02 08:28:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一组ndJOSN数据集,如下所示:

   {'ADDRESS_CITY': 'Whittier', 'ADDRESS_LINE_1': '905 Greenleaf Avenue', 'ADDRESS_STATE': 'CA', 'ADDRESS_ZIP': '90402',},
   {'ADDRESS_CITY': 'Cedar Falls', 'ADDRESS_LINE_1': '93323 Maplewood Dr', 'ADDRESS_STATE': 'CA', 'ADDRESS_ZIP': '95014'}

我需要将上面的值传递到api请求中,特别是下面格式的主体

data=[
        {
            "addressee":"Greenleaf Avenue",
            "street":"905 Greenleaf Avenue",
            "city":"Whittier",
            "state":"CA",
            "zipcode":"90402",
            
        },
        {
            "addressee":"93323",
            "street":"Maplewood Dr",
            "city":"Cedar Falls",
            "state":"CA",
            "zipcode":"95014",
        
        }
]

正如您所看到的,密钥是不同的,因此我需要更改密钥,使其与正确的数据对齐,并将它们与新的密钥名称一起传递(即地址\u行\u 1传递给收件人)-此请求中将有10k个地址

在我的第一个示例中,我没有注意到这一点,但每个地址都有一个相关联的ID——我必须删除它才能发出请求,然后再重新添加。 所以我最终解决了下面的问题——任何更具Python风格的问题,这些问题对我来说都不是那么有说服力

addresses = ndjson.loads(addresses)
data = json.loads(json.dumps(addresses).replace('"ADDRESS_CITY"','"city"').replace('"ADDRESS_LINE_1"','"street"').replace('"ADDRESS_STATE"','"state"').replace('"ADDRESS_ZIP"','"zipcode"'))
ids = []
for i in data:
    i['candidates'] = 1
    ids.append(i["ID"])
    del i["ID"]

response = requests.request("POST", url, json=data)

resp_data = response.json()

a = 0
for i in resp_data:
    i['ID'] = ids[a]
    x = i['ID'] = ids[a]
    a = a + 1

Tags: idjsonidsstreetcitydataaddressline
2条回答

如果您想让事情变得更简单一点,我建议使用data classes对输入数据进行建模。这样做的主要好处是,您可以对属性使用dot.访问,而不需要使用具有动态键的字典。您还可以从类型暗示中获益,因此您的IDE也应该能够更好地帮助您

在本例中,我建议将它与一个JSON序列化库(如dataclass-wizard)配对,它实际上完美地支持这个用例。从最新版本v0.15.0开始,它还应该支持从序列化/转储过程中排除字段

下面是我放在一起的一个简单示例,它使用了上面所需的键映射:

import json
from dataclasses import dataclass, field
# note: for python 3.9+, you can import this from `typing` instead
from typing_extensions import Annotated

from dataclass_wizard import JSONWizard, json_key


@dataclass
class AddressInfo(JSONWizard):
    """
    AddressInfo dataclass

    """
    city: Annotated[str, json_key('ADDRESS_CITY')]
    street: Annotated[str, json_key('ADDRESS_LINE_1')]
    state: Annotated[str, json_key('ADDRESS_STATE')]

    # pass `dump=False`, so we exclude the field in serialization.
    id: Annotated[int, json_key('ID', dump=False)]

    # you could also annotate the below like `Union[str, int]`
    # if you want to retain it as a string.
    zipcode: Annotated[int, json_key('ADDRESS_ZIP')]

    # exclude this field from the constructor (and from the
    # de-serialization process)
    candidates: int = field(default=1, init=False)

以及上述各项的示例用法:

input_obj = [{'ADDRESS_CITY': 'Whittier', 'ADDRESS_LINE_1': '905 Greenleaf Avenue',
              'ADDRESS_STATE': 'CA', 'ADDRESS_ZIP': '90402',
              'ID': 111},
             {'ADDRESS_CITY': 'Cedar Falls', 'ADDRESS_LINE_1': '93323 Maplewood Dr',
              'ADDRESS_STATE': 'CA', 'ADDRESS_ZIP': '95014',
              'ID': 222}]

addresses = AddressInfo.from_list(input_obj)

print('  Addresses')
for a in addresses:
    print(repr(a))

out_list = [a.to_dict() for a in addresses]

print('  To JSON')
print(json.dumps(out_list, indent=2))

# alternatively, with the latest version (0.15.1)
# print(AddressInfo.list_to_json(addresses, indent=2))

注意:您仍然可以正常访问每个地址的id,即使JSON结果中省略了此字段

使用字典翻译:

translations = {
"ADDRESS_CITY": "city"} # etc
input_data = ... # your data here
data = [{translations[k]: v for k, v in row.items()} for row in input_data]

相关问题 更多 >

    热门问题