使用Cerberus验证嵌套JSON后,RequestParser参数配置问题求助
解决方案
核心问题拆解
你遇到的两个关键点:
- 不知道如何让
RequestParser正确读取嵌套JSON请求体 - 验证后返回的字典无法映射到自定义类
分步解决
1. 正确配置RequestParser读取JSON请求体
如果前端是将整个嵌套JSON作为请求体发送,需要给add_argument指定location='json',同时设置合理的参数名(比如'payload'或'observation'),且不需要action='append'(该参数用于接收数组型重复参数,你的场景是单个完整结构)。
2. 验证后将字典转换为自定义类
在Cerberus验证通过后,手动将返回的字典实例化为你的自定义类。推荐使用Python 3.7+的dataclasses来简化类定义和转换逻辑。
修改后的完整代码示例
第一步:定义自定义数据类
from dataclasses import dataclass, asdict import cerberus as cerb import json from flask_restful import Resource, reqparse # 用dataclass定义嵌套结构,自动生成初始化方法和序列化逻辑 @dataclass class InputField: field_name: str field_text: str @dataclass class InputItem: type: str id: int fields: list[InputField] @dataclass class AuditInfo: audit_id: int audit_name: str @dataclass class Requester: GID: str roles: str @dataclass class AuthInfo: checksum: str validuntil: str @dataclass class Observation: input_item: InputItem result_item_types: list audit: AuditInfo requested_by: Requester authentication: AuthInfo
第二步:修改验证器,添加类转换逻辑
def obs_validator(value): schema = { 'input_item': { 'type': 'dict', 'schema': { 'type': {'type': 'string', 'required': True}, 'id': {'type': 'integer', 'required': True}, 'fields': { 'type': 'list', 'required': True, 'schema': { 'type': 'dict', 'schema': { 'field_name': {'type': 'string', 'required': True}, 'field_text': {'type': 'string', 'required': True} } } } } }, 'result_item_types': {'type': 'list', 'required': True}, 'audit': { 'type': 'dict', 'schema': { 'audit_id': {'type': 'integer', 'required': True}, 'audit_name': {'type': 'string', 'required': True} } }, 'requested_by': { 'type': 'dict', 'schema': { 'GID': {'type': 'string', 'required': True}, 'roles': {'type': 'string', 'required': True} } }, 'authentication': { 'type': 'dict', 'schema': { 'checksum': {'type': 'string', 'required': True}, 'validuntil': {'type': 'string', 'required': True} } } } v = cerb.Validator(schema) if v.validate(value): # 逐层将字典转换为自定义类实例 input_fields = [InputField(**f) for f in value['input_item']['fields']] input_item = InputItem( type=value['input_item']['type'], id=value['input_item']['id'], fields=input_fields ) return Observation( input_item=input_item, result_item_types=value['result_item_types'], audit=AuditInfo(**value['audit']), requested_by=Requester(**value['requested_by']), authentication=AuthInfo(**value['authentication']) ) else: raise ValueError(json.dumps(v.errors))
第三步:配置RequestParser并修改Resource
put_args = reqparse.RequestParser() # 指定从JSON请求体读取完整结构,参数名为observation put_args.add_argument("observation", type=obs_validator, location='json') class TextResource(Resource): def put(self): args = put_args.parse_args() # args['observation']现在是Observation类的实例 # 使用asdict将类实例转换为可序列化的字典返回 return asdict(args['observation']), 201
关键说明
location='json':告诉RequestParser从HTTP请求的JSON体中读取参数,而非URL或表单数据- 嵌套类转换:需要逐层处理字典到类的映射,
dataclass的**语法可以快速将字典键值对传递给类的初始化方法 - 序列化返回:使用
dataclasses.asdict()可以方便地将自定义类实例转换为JSON可序列化的字典
内容的提问来源于stack exchange,提问作者Turan Toprak Bilge
相关产品推荐
相关产品推荐

