使用 Pydantic 解包嵌套 JSON 时跳过字典级别
Skipping dict levels when unpacking nested JSON with Pydantic
我正在从 API 中获取并得到 JSON 响应,如下所示:
{
"features": {
"due_dates": {
"enabled": true,
"start_date": false,
"remap_due_dates": true,
"remap_closed_due_date": false
},
"sprints": {
"enabled": false
},
"points": {
"enabled": false
},
"custom_items": {
"enabled": false
},
"tags": {
"enabled": true
},
"time_estimates": {
"enabled": true
},
"checklists": {
"enabled": true
},
"zoom": {
"enabled": false
},
"milestones": {
"enabled": false
},
"custom_fields": {
"enabled": true
},
"remap_dependencies": {
"enabled": true
},
"dependency_warning": {
"enabled": true
},
"multiple_assignees": {
"enabled": true
},
"portfolios": {
"enabled": true
},
"emails": {
"enabled": true
}
}
我的 class 设置如下:
class Features(BaseModel):
multiple_assignees: bool = False
start_date: bool = False
remap_due_dates: bool = False
remap_closed_due_date: bool = False
time_tracking: bool = False
tags: bool = False
time_estimates: bool = False
checklists: bool = False
custom_fields: bool = False
remap_dependencies: bool = False
dependency_warning: bool = False
portfolios: bool = False
points: bool = False
custom_items: bool = False
zoom: bool = False
milestones: bool = False
emails: bool = False
我想做的是将此 JSON 解压缩到功能对象中,并为每个相应的属性使用“enabled”键中的值。我想这样做以避免必须为冲刺、积分、custom_items 等设置 class。是否可以只获取嵌套的“已启用”布尔值并跳过设置每个 class?
不幸的是,我认为没有一种非常简单的方法可以做到这一点。我想最直接的方法是使用 this issue 中提到的根验证器,这样我们就可以使用我们自己想要的逻辑来解包字段。像这样的东西应该适用于:
import json
from pydantic import BaseModel, root_validator
class Features(BaseModel):
multiple_assignees: bool = False
start_date: bool = False
remap_due_dates: bool = False
remap_closed_due_date: bool = False
time_tracking: bool = False
tags: bool = False
time_estimates: bool = False
checklists: bool = False
custom_fields: bool = False
remap_dependencies: bool = False
dependency_warning: bool = False
portfolios: bool = False
points: bool = False
custom_items: bool = False
zoom: bool = False
milestones: bool = False
emails: bool = False
@root_validator(pre=True)
def extract_features(cls, v):
# Unwrap features and all 'enabled' values for each field within
res = {k: v['enabled'] if isinstance(v, dict) and 'enabled' in v else v
for k, v in v['features'].items()}
# Map due date fields which are a bit different
due_dates = v['features'].get('due_dates')
if due_dates:
for field in ('start_date',
'remap_due_dates',
'remap_closed_due_date'):
res[field] = due_dates.get(field, False)
return res
string = """
{
"features": {
"due_dates": {
"enabled": true,
"start_date": false,
"remap_due_dates": true,
"remap_closed_due_date": false
},
"sprints": {
"enabled": false
},
"points": {
"enabled": false
},
"custom_items": {
"enabled": false
},
"tags": {
"enabled": true
},
"time_estimates": {
"enabled": true
},
"checklists": {
"enabled": true
},
"zoom": {
"enabled": false
},
"milestones": {
"enabled": false
},
"custom_fields": {
"enabled": true
},
"remap_dependencies": {
"enabled": true
},
"dependency_warning": {
"enabled": true
},
"multiple_assignees": {
"enabled": true
},
"portfolios": {
"enabled": true
},
"emails": {
"enabled": true
}
}
}
"""
d = json.loads(string)
x = Features(**d)
print(x)
我正在从 API 中获取并得到 JSON 响应,如下所示:
{
"features": {
"due_dates": {
"enabled": true,
"start_date": false,
"remap_due_dates": true,
"remap_closed_due_date": false
},
"sprints": {
"enabled": false
},
"points": {
"enabled": false
},
"custom_items": {
"enabled": false
},
"tags": {
"enabled": true
},
"time_estimates": {
"enabled": true
},
"checklists": {
"enabled": true
},
"zoom": {
"enabled": false
},
"milestones": {
"enabled": false
},
"custom_fields": {
"enabled": true
},
"remap_dependencies": {
"enabled": true
},
"dependency_warning": {
"enabled": true
},
"multiple_assignees": {
"enabled": true
},
"portfolios": {
"enabled": true
},
"emails": {
"enabled": true
}
}
我的 class 设置如下:
class Features(BaseModel):
multiple_assignees: bool = False
start_date: bool = False
remap_due_dates: bool = False
remap_closed_due_date: bool = False
time_tracking: bool = False
tags: bool = False
time_estimates: bool = False
checklists: bool = False
custom_fields: bool = False
remap_dependencies: bool = False
dependency_warning: bool = False
portfolios: bool = False
points: bool = False
custom_items: bool = False
zoom: bool = False
milestones: bool = False
emails: bool = False
我想做的是将此 JSON 解压缩到功能对象中,并为每个相应的属性使用“enabled”键中的值。我想这样做以避免必须为冲刺、积分、custom_items 等设置 class。是否可以只获取嵌套的“已启用”布尔值并跳过设置每个 class?
不幸的是,我认为没有一种非常简单的方法可以做到这一点。我想最直接的方法是使用 this issue 中提到的根验证器,这样我们就可以使用我们自己想要的逻辑来解包字段。像这样的东西应该适用于:
import json
from pydantic import BaseModel, root_validator
class Features(BaseModel):
multiple_assignees: bool = False
start_date: bool = False
remap_due_dates: bool = False
remap_closed_due_date: bool = False
time_tracking: bool = False
tags: bool = False
time_estimates: bool = False
checklists: bool = False
custom_fields: bool = False
remap_dependencies: bool = False
dependency_warning: bool = False
portfolios: bool = False
points: bool = False
custom_items: bool = False
zoom: bool = False
milestones: bool = False
emails: bool = False
@root_validator(pre=True)
def extract_features(cls, v):
# Unwrap features and all 'enabled' values for each field within
res = {k: v['enabled'] if isinstance(v, dict) and 'enabled' in v else v
for k, v in v['features'].items()}
# Map due date fields which are a bit different
due_dates = v['features'].get('due_dates')
if due_dates:
for field in ('start_date',
'remap_due_dates',
'remap_closed_due_date'):
res[field] = due_dates.get(field, False)
return res
string = """
{
"features": {
"due_dates": {
"enabled": true,
"start_date": false,
"remap_due_dates": true,
"remap_closed_due_date": false
},
"sprints": {
"enabled": false
},
"points": {
"enabled": false
},
"custom_items": {
"enabled": false
},
"tags": {
"enabled": true
},
"time_estimates": {
"enabled": true
},
"checklists": {
"enabled": true
},
"zoom": {
"enabled": false
},
"milestones": {
"enabled": false
},
"custom_fields": {
"enabled": true
},
"remap_dependencies": {
"enabled": true
},
"dependency_warning": {
"enabled": true
},
"multiple_assignees": {
"enabled": true
},
"portfolios": {
"enabled": true
},
"emails": {
"enabled": true
}
}
}
"""
d = json.loads(string)
x = Features(**d)
print(x)