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

DRF MultiPartParser解析JSON为字符串的问题解决咨询

解决DRF多部分请求中JSON字段被解析为字符串的问题

当使用DRF的MultiPartParser处理包含JSON数据和文件的multipart请求时,JSON部分会被解析成字符串而非字典,添加JSONParser也无法解决——因为JSONParser仅处理纯application/json类型的请求,对multipart/form-data类型的请求不起作用。

下面提供几种可行的解决办法:

方法一:手动解析JSON字符串(快速解决)

直接在视图中对拿到的JSON字符串进行解析,代码改动最小:

import json
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import MultiPartParser
from rest_framework.decorators import api_view, parser_classes

@api_view(['POST'])
@parser_classes([MultiPartParser])
def import_files(request: Request) -> Response:
    data = request.data
    # 将JSON字符串解析为字典
    json_data = json.loads(data['json'])
    print(type(json_data))  # 此时类型为dict
    # 后续可直接使用json_data处理业务逻辑
    return Response("Success", status=200)

这种方式无需修改客户端代码,适合快速解决单个视图的问题。

方法二:自定义解析器(一劳永逸)

如果多个视图都需要处理这类请求,可以自定义一个继承自MultiPartParser的解析器,自动识别并解析application/json类型的请求部分:

import json
from rest_framework.parsers import MultiPartParser
from rest_framework.exceptions import ParseError

class MultiPartJSONParser(MultiPartParser):
    def parse(self, stream, media_type=None, parser_context=None):
        # 先调用父类方法获取原始解析结果
        parsed_result = super().parse(stream, media_type, parser_context)
        processed_data = {}
        
        for key, value in parsed_result.data.items():
            # 检查当前字段的Content-Type是否为application/json
            if hasattr(value, 'content_type') and value.content_type == 'application/json':
                try:
                    # 读取内容并解析为JSON字典
                    decoded_value = value.read().decode('utf-8')
                    processed_data[key] = json.loads(decoded_value)
                except json.JSONDecodeError:
                    raise ParseError(f"字段 {key} 中的JSON格式无效")
            else:
                processed_data[key] = value
        
        # 替换原始数据为处理后的结果
        parsed_result.data = processed_data
        return parsed_result

然后在视图中使用这个自定义解析器:

@api_view(['POST'])
@parser_classes([MultiPartJSONParser])
def import_files(request: Request) -> Response:
    data = request.data
    print(type(data['json']))  # 直接得到dict类型
    return Response("Success", status=200)

这种方式一次定义,多处复用,适合有大量类似场景的项目。

方法三:调整客户端请求(可选)

如果允许修改客户端代码,可以简化请求构造,但本质还是需要服务端解析,不如前两种方法高效:

import requests
import json

# 直接将JSON字符串作为普通表单字段传递
payload = {"key": "value"}
multipart_data = {
    'json': json.dumps(payload),
}
files = {
    'file': ('test.xlsx', open('test.xlsx', 'rb'), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
}

put_response = requests.post(endpoint + "feature/", data=multipart_data, files=files)
print(put_response.json())

服务端依然需要用json.loads解析,和方法一逻辑一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 14:47:46