Django REST Framework:字符串与整数的双向序列化转换问题
问题描述
我刚接触Django和Django REST Framework,现在需要处理第三方API返回的JSON响应,做序列化与反序列化操作,把返回的字符串字段转换成系统内的数值类型。
第三方API返回的JSON格式如下:
{ "result": "win" } // 其他可选值为"loss"/"inconclusive"/"pending"
对应的Django模型定义:
class Experiment(Model): RESULTS = ( (1, 'win'), (2, 'loss'), (3, 'inconclusive'), ) inferred_result = models.IntegerField(choices=RESULTS, null=True, blank=True)
我写的序列化器类:
class ResultsSerializer(serializers.ModelSerializer): # 需要实现"result"字符串与整数的双向转换 class Meta: model = models.Experiment
目前我只知道怎么把整数转换成对应字符串,但不清楚如何把第三方API返回的字符串转换成模型里的整数值,想请教具体的实现方法。
解决方案
你可以通过自定义序列化字段来实现这种双向转换,这是DRF里处理自定义类型映射的常用方式,既能把模型中的整数转成API所需的字符串,也能把API返回的字符串转成模型对应的整数。具体实现步骤如下:
1. 定义自定义字段类
创建一个继承自serializers.Field的自定义字段,重写两个核心方法:to_representation(负责序列化:模型值转API输出)和to_internal_value(负责反序列化:API输入转模型值):
from rest_framework import serializers from .models import Experiment class ResultField(serializers.Field): # 先把模型的choices转换成双向映射字典,方便快速查找 _str_to_int = {v: k for k, v in Experiment.RESULTS} # 处理第三方API特有的"pending"值,这里对应模型里的null,可根据需求调整 _str_to_int['pending'] = None def to_representation(self, value): # 把模型中的整数转换成对应字符串 if value is None: return 'pending' return dict(Experiment.RESULTS).get(value, 'pending') def to_internal_value(self, data): # 把API传入的字符串转换成模型对应的整数 if not isinstance(data, str): raise serializers.ValidationError("Result must be a string.") # 忽略大小写(可选,根据API实际情况调整) normalized_data = data.lower() result = self._str_to_int.get(normalized_data) if result is None and normalized_data != 'pending': raise serializers.ValidationError(f"Invalid result value: {data}") return result
2. 在序列化器中使用自定义字段
在你的ResultsSerializer里,用自定义的ResultField替换默认的inferred_result字段,并指定字段名为result(对应第三方API的字段名):
class ResultsSerializer(serializers.ModelSerializer): result = ResultField(source='inferred_result') class Meta: model = Experiment fields = ['result'] # 可根据需求添加其他需要序列化的字段
关键逻辑说明
to_representation:当把模型数据返回给前端/第三方时,将inferred_result的整数(比如1)转换成对应的字符串"win",如果是None则返回"pending"。to_internal_value:当接收第三方API的JSON数据时,将字符串(比如"loss")转换成模型对应的整数2,遇到"pending"则返回None(对应模型字段的null),如果是无效值会抛出验证错误。- 映射字典:通过
{v: k for k, v in Experiment.RESULTS}反转模型的choices,避免写大量if-else判断,让转换逻辑更简洁高效。
测试示例
- 序列化(模型转API):如果
Experiment实例的inferred_result是3,序列化后会输出{"result": "inconclusive"}。 - 反序列化(API转模型):如果传入
{"result": "pending"},inferred_result会被设为None;传入{"result": "loss"},则会被设为2。
刚接触DRF的话,自定义字段是处理这类自定义转换的核心技巧,多练几次就能熟练掌握啦!
内容的提问来源于stack exchange,提问作者Kartik
相关产品推荐
相关产品推荐

