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

如何用Django REST Framework序列化器优雅实现嵌套JSON反序列化扁平化

DRF反序列化嵌套JSON扁平化的优雅实现方案

你需要的类似序列化阶段的点语法source写法完全可以实现,提供两种适配不同场景的方案:

方案1:单次场景快速实现

适合只需要处理个别接口的场景,不需要额外封装,直接重写to_internal_value方法完成结构转换,字段原生验证逻辑完全保留:

class TheFlattener(serializers.Serializer):
    # 直接定义最终要的扁平字段
    name = serializers.CharField(max_length=50)
    lat = serializers.FloatField()
    lon = serializers.FloatField()

    def to_internal_value(self, data):
        # 先把输入的嵌套结构转成和序列化器字段匹配的扁平结构
        flattened_data = {
            "name": data.get("objectName"),
            "lat": data.get("geoInfo", {}).get("latitude"),
            "lon": data.get("geoInfo", {}).get("longitude"),
        }
        # 调用父类逻辑走正常的字段验证
        return super().to_internal_value(flattened_data)

    def create(self, validated_data):
        return Thing(**validated_data)

方案2:通用场景封装,支持和序列化一致的点语法source

适合需要频繁处理嵌套反序列化的场景,封装通用基类后,就可以和序列化阶段一样用点语法指定嵌套字段路径,不需要额外写转换逻辑:

第一步:封装通用扁平化反序列化基类

class FlattenDeserializer(serializers.Serializer):
    def to_internal_value(self, data):
        processed_data = {}
        for field_name, field in self.fields.items():
            # 读取source配置的路径,默认和字段名一致
            source_path = field.source if field.source != field_name else field_name
            # 按点拆分路径,逐层取值
            value = data
            for key in source_path.split("."):
                if not isinstance(value, dict) or key not in value:
                    value = None
                    break
                value = value[key]
            processed_data[field_name] = value
        # 传入转换后的扁平数据走原生验证逻辑
        return super().to_internal_value(processed_data)

第二步:业务序列化器直接继承使用

写法和序列化阶段完全一致,没有额外学习成本:

class TheFlattener(FlattenDeserializer):
    # 直接用点语法指定输入数据的嵌套路径
    name = serializers.CharField(max_length=50, source="objectName")
    lat = serializers.FloatField(source="geoInfo.latitude")
    lon = serializers.FloatField(source="geoInfo.longitude")

    def create(self, validated_data):
        # validated_data已经是扁平化结构,直接使用即可
        return Thing(**validated_data)

两种方案都不需要再定义嵌套序列化器,也不需要在create方法里做额外的字段弹出和映射,和原有实现相比代码更简洁,逻辑更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 03:06:04