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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:50:57