遭遇json.decoder.JSONDecodeError,请求排查Django接口POST解析问题
Django /voice_chat/rooms接口POST请求JSON解析错误修复
错误现象
在Django项目的/voice_chat/rooms接口处理POST请求时,触发json.decoder.JSONDecodeError,具体错误信息为:
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
完整错误栈
ERROR 2022-11-08 13:29:54,926: Internal Server Error: /voice_chat/rooms Traceback (most recent call last): File "C:\Users\15512\anaconda3\lib\site-packages\asgiref\sync.py", line 451, in thread_handler raise exc_info[1] File "C:\Users\15512\anaconda3\lib\site-packages\django\core\handlers\exception.py", line 38, in inner response = await get_response(request) File "C:\Users\15512\anaconda3\lib\site-packages\django\core\handlers\base.py", line 233, in _get_response_async response = await wrapped_callback(request, *callback_args, **callback_kwargs) File "C:\Users\15512\anaconda3\lib\site-packages\asgiref\sync.py", line 414, in __call__ ret = await asyncio.wait_for(future, timeout=None) File "C:\Users\15512\anaconda3\lib\asyncio\tasks.py", line 455, in wait_for return await fut File "C:\Users\15512\anaconda3\lib\concurrent\futures\thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs) File "C:\Users\15512\anaconda3\lib\site-packages\asgiref\sync.py", line 455, in thread_handler return func(*args, **kwargs) File "C:\Users\15512\anaconda3\lib\site-packages\django\views\generic\base.py", line 69, in view return self.dispatch(request, *args, **kwargs) request_body = json.loads(decode_request) File "C:\Users\15512\anaconda3\lib\json\__init__.py", line 357, in loads return _default_decoder.decode(s) File "C:\Users\15512\anaconda3\lib\json\decoder.py", line 337, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "C:\Users\15512\anaconda3\lib\json\decoder.py", line 355, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) ERROR 2022-11-08 13:29:54,959: HTTP POST /voice_chat/rooms 500 [0.32, 127.0.0.1:54258]
问题根源
代码中通过json.loads()解析请求体,但实际接收到的是x-www-form-urlencoded格式的键值对参数(包含AccountSid、roomName等字段),而非预期的JSON格式,导致JSON解析失败。
原代码示例
def post(self, request, *args, **kwargs): decode_request = request.body.decode("utf-8") print('decoded request body', decode_request) request_body = json.loads(decode_request) # print('request body', request_body) room_name = request_body.get("roomName") participant_label = request_body["participantLabel"] # print('username', curr_username) response = VoiceResponse() dial = Dial() dial.conference( name=room_name, participant_label=participant_label, start_conference_on_enter=True, ) response.append(dial) return HttpResponse(response.to_xml(), content_type="text/xml")
请求体对比
预期JSON格式请求体
{"roomName":"testingUseremmanuelS21","participantLabel":"emmanuelS21","matchedUser":"testingUser"}
实际接收的x-www-form-urlencoded格式内容
AccountSid=***&ApiVersion=2010-04-01&ApplicationSid=***&CallSid=CAf4e ***&CallStatus=ringing&Called=&Caller=client%3AemmanuelS21&Direction=inbound&From=client%3AemmanuelS21&To=&participantLabel=emmanuelS21&roomName=testingUseremmanuelS21
修复方案
Django会自动解析x-www-form-urlencoded格式的请求体,直接通过request.POST获取参数即可,无需手动解析请求体。如果需要同时兼容JSON和表单两种格式,可以先判断请求的Content-Type头,再选择对应的解析方式。
修复后代码
def post(self, request, *args, **kwargs): # 直接从request.POST获取表单格式的参数 room_name = request.POST.get("roomName") participant_label = request.POST.get("participantLabel") # 如果需要兼容JSON格式,可以添加如下判断 # if request.content_type == 'application/json': # decode_request = request.body.decode("utf-8") # request_body = json.loads(decode_request) # room_name = request_body.get("roomName") # participant_label = request_body.get("participantLabel") response = VoiceResponse() dial = Dial() dial.conference( name=room_name, participant_label=participant_label, start_conference_on_enter=True, ) response.append(dial) return HttpResponse(response.to_xml(), content_type="text/xml")
内容的提问来源于stack exchange,提问作者Emm
相关产品推荐
相关产品推荐

