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
相关产品推荐
相关产品推荐

