DRF序列化器如何实现字典列表结构字段的正确序列化
问题原因
你遇到的两个报错原因非常明确:
AttributeError: 'list' object has no attribute 'items':你给列表结构的other字段错用了DictField,DictField的处理逻辑是对传入对象调用.items()遍历键值对,传入列表自然触发报错。TypeError: Object of type PoCo is not JSON serializable:你使用ListField时没有指定子元素的序列化规则,DRF无法识别你自定义的PoCo类,直接将原生对象传给JSON编码器就会触发该错误。
另外你贴的原始序列化器还有一处语法错误:DecimalField定义行末尾缺少右括号,运行时会直接报语法错误。
实现方案
DRF处理嵌套的列表+字典结构,不能直接使用无参数的ListField/DictField,需要按照嵌套层级逐层定义对应序列化器,明确每个字段的处理逻辑,步骤如下:
- 确认你已经实现了
p3字段对应结构的序列化器(即你提到的已经写好的、处理p3字典/PoCo对象的序列化器,下文假设名为P3Serializer) - 为
other列表内的单个字典元素定义对应的嵌套序列化器 - 在主序列化器中给
other字段用ListField,通过child参数指定单元素的序列化器即可
完整实现代码:
from rest_framework import serializers from decimal import Decimal # 这是你已经实现好的、处理p3结构的序列化器,此处仅做占位示例 class P3Serializer(serializers.Serializer): # 替换为你自己的p3字段定义 pass # 定义other列表中单个元素的序列化规则 class OtherItemSerializer(serializers.Serializer): p1 = serializers.IntegerField(required=True) p2 = serializers.IntegerField(required=True) p3 = P3Serializer(required=True) # 修正后的主序列化器 class MySerializer(serializers.Serializer): # 补全了原有缺失的右括号 num = serializers.DecimalField(max_digits=10, decimal_places=4, required=True) uid = serializers.CharField(max_length=30, required=True) # 新增other字段,指定子元素序列化逻辑 other = serializers.ListField( child=OtherItemSerializer(), required=True # 可根据你的业务需求调整为False )
使用说明
- 序列化输出场景:只要传入序列化器的对象/字典中,
other对应的值是列表结构,每个列表元素包含p1、p2、p3三个键/属性,其中p3是P3Serializer可以处理的对象(即你的PoCo实例),就可以正常输出你预期的字典列表结构,不会触发序列化报错。 - 反序列化校验场景:该写法会自动逐层校验字段类型、必填规则,
p3部分会自动复用你已经写好的P3Serializer的校验逻辑,不需要额外写重复的校验代码。 - 不要尝试用无child参数的
ListField或者直接用DictField处理这种多层嵌套的自定义结构,前者无法处理自定义类实例,后者和列表数据类型不匹配。
内容的提问来源于stack exchange,提问作者user2194805
相关产品推荐
相关产品推荐

