为何POST请求中ids转字符串可行、传列表却触发TypeError?
为什么直接传列表作为POST请求参数会触发"TypeError: expected string or buffer"错误?
这问题我之前排查过类似的,核心原因是服务器端的处理逻辑和前端的传参方式不匹配,咱们一步步拆解:
先看两种请求的本质差异
当你设置content_type='application/json'并且用json.dumps(data)发送请求时,服务器框架(比如Django REST Framework)会自动把请求体的JSON字符串解析成Python字典,存到request.data里。
无效请求(直接传列表)的问题出在哪:
- 前端传的
data里ids是[5],经过json.dumps转成JSON后,服务器解析出来的request.data.get('ids')是Python列表对象[5]。 - 但服务器端却执行了
ids = json.loads(ids_json)——json.loads()要求参数必须是字符串或字节流,给它传一个列表对象,自然就抛出TypeError: expected string or buffer了。
- 前端传的
有效请求(转成字符串)为什么能工作:
- 这里你用
str([pk])把列表转成了字符串"[5]",经过json.dumps后,服务器解析出来的request.data.get('ids')还是字符串"[5]"。 - 这个字符串刚好符合JSON数组的格式,所以
json.loads(ids_json)能正常把它解析成列表[5],请求也就顺利执行了。不过这其实是个巧合,不是正确的传参姿势。
- 这里你用
两种解决方案
方案一:修改服务器端代码(推荐)
既然前端已经正确传递了JSON格式的请求,服务器端不需要对ids做二次解析,直接用解析后的列表就行:
# 去掉多余的json.loads调用,直接使用解析后的列表 ids = request.data.get('ids')
这是最合理的做法,符合JSON接口的设计规范。
方案二:如果必须保留服务器端现有逻辑
那前端需要把列表转成标准JSON字符串(注意不是Python的str(),而是用json.dumps())再传:
pk = 5 data = { 'ids': json.dumps([pk]), 'latitude': 0, 'longitude': 0, } response = self.client.post( '/api/{}/endpoint'.format(settings.DEFAULT_VERSION), data=json.dumps(data, indent=4), content_type='application/json', HTTP_AUTHENTICATION=user.access_token, )
不过这种方式属于嵌套JSON,完全没必要,除非有特殊的历史原因必须这么做。
简单总结:你之前的第一种写法能运行只是碰巧str([pk])生成的字符串符合JSON格式,但正确的姿势是前端直接传列表,后端直接使用解析后的列表对象。
内容的提问来源于stack exchange,提问作者user9537832
相关产品推荐
相关产品推荐

