You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF序列化器is_valid无报错,但validated_data为空(第三方API场景)

问题:DRF序列化器is_valid()返回True,但validated_data为空OrderedDict

在对第三方API返回的数据进行反序列化时,出现以下问题:

  • serializer.is_valid()返回True,且serializer.errors为空字典
  • serializer.validated_data返回空的OrderedDict

但验证原始数据时,能够正常获取到id和code字段的值(示例输出:9 DZ)。

序列化器代码

from rest_framework import serializers

class CountrySerializer(serializers.Serializer):
    countryId = serializers.SerializerMethodField()
    countryName = serializers.SerializerMethodField()

    def get_countryId(self, data):
        return data["id"]

    def get_countryName(self, data):
        return data["code"]

调用代码

from serializers import CountrySerializer
import requests

response = requests.get(url)
jsonResponse = response.json()
data = jsonResponse[0]
serializer = CountrySerializer(data=data)

# 执行输出
print(serializer.is_valid())  # 输出:True
print(serializer.errors)     # 输出:{}
print(serializer.validated_data)  # 输出:OrderedDict()

原因分析

SerializerMethodField是DRF中的只读字段,设计目的仅用于序列化过程(将Python对象转换为JSON格式),不会参与反序列化的字段验证和数据提取流程。

当使用CountrySerializer(data=data)进行反序列化时,DRF会自动忽略所有只读字段:

  • 不对这些字段做校验,因此is_valid()返回True
  • 不会将对应数据加入validated_data,最终得到空的OrderedDict

解决方案

根据实际需求选择对应方案:

方案1:仅用于序列化(转换数据格式输出)

如果只是需要把第三方API返回的数据转换成指定格式(如将id映射为countryId,code映射为countryName),不需要反序列化校验,直接用instance参数初始化序列化器即可:

serializer = CountrySerializer(instance=data)
print(serializer.data)
# 输出示例:{'countryId': 9, 'countryName': 'DZ'}

方案2:需要反序列化并提取数据

如果要在反序列化过程中提取字段到validated_data,将SerializerMethodField替换为普通字段,通过source参数映射原始数据字段:

from rest_framework import serializers

class CountrySerializer(serializers.Serializer):
    countryId = serializers.IntegerField(source='id')
    countryName = serializers.CharField(source='code')

此时执行反序列化:

serializer = CountrySerializer(data=data)
serializer.is_valid()
print(serializer.validated_data)
# 输出示例:OrderedDict([('id', 9), ('code', 'DZ')])

如果需要validated_data直接用countryId和countryName作为键名,可重写validate方法:

class CountrySerializer(serializers.Serializer):
    id = serializers.IntegerField()
    code = serializers.CharField()

    def validate(self, attrs):
        attrs['countryId'] = attrs.pop('id')
        attrs['countryName'] = attrs.pop('code')
        return attrs

此时validated_data输出:

print(serializer.validated_data)
# 输出示例:OrderedDict([('countryId', 9), ('countryName', 'DZ')])

内容的提问来源于stack exchange,提问作者Hanna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 04:35:32