如何在Python/Django中将字典列表转换为JSON?

16

我在Google上搜索到一个答案,但对我没有用。我需要在Django中以JsonResponse的形式发送一个列表,类似于这个:

list_to_json =[{"title": "hello there",
                "link": "www.domain.com",
                "date":   ...},
               {},{},{},...]

我正在按照StackOverflow上的问题1问题2将其转换为JSON,但对我来说并不起作用。我收到以下错误:

为了允许序列化非字典对象,请将safe参数设置为False

这是我的代码:

    def json_response(request):
        list_to_json=[{"title": ..., "link": ..., "date": ...},{...}]
        return JsonResponse(json.dumps(list_to_json) )

1
这个解决了你的问题吗:return JsonResponse(json.dumps(list_to_json), safe=False) - jape
你样本中第二行的Python字典是无效的。请同时包含完整的堆栈跟踪。否则我认为很难跟踪。 - Dilettant
2
JsonResponse 的整个意义在于它将为您序列化数据。对数据调用 json.dumps() 将会使其编码两次。 - knbk
4个回答

38
return JsonResponse(list_to_json, safe=False)

请查看文档

安全布尔参数默认为True。如果将其设置为False,则可以传递任何对象进行序列化(否则只允许dict实例)。如果safe为True并且非字典对象作为第一个参数传递,将引发TypeError。


1
Ahop 就像将列表作为字符串返回。 - shuboy2014
1
运行得非常顺利。 - Ajay Kumar

4
为了帮助任何想知道为什么这个默认情况下不是“安全”的人,我添加了这个答案。将非字典数据结构打包到响应中会使服务容易受到ES5之前的JSON劫持攻击。
基本上,你现在使用的JSONResponse,如果用户已经通过身份验证登录了你的网站,他现在可以检索到那些{title, link, date}对象的列表,这没问题。但是,攻击者可以将该端点包含在自己的恶意页面中作为脚本源(跨站点脚本包含,又称XSSI):
<script src="https://www.yourwebsite.com/secretlinks/"></script>

接着,如果一个毫不知情的已验证用户浏览到恶意页面,浏览器将不知不觉地从你的网站请求数据数组。由于你的服务只返回未分配的数组,攻击者必须还要污染 js 数组构造函数(这是在 ES5 中修复的攻击部分)。 在 ES5 之前,攻击者可以像这样简单地覆盖数组构造函数:

Array = function() {secret = this;}

现在secret包含您的字典列表,并可供攻击者脚本中的其余部分使用,攻击者可以将其发送到自己的服务器。ES5通过强制使用方括号由默认的数组构造函数进行评估来解决了这个问题。
为什么字典对象从来没有出现过这个问题?因为javascript中的花括号表示一个隔离的作用域,所以攻击者无法将自己的代码注入到由花括号括起来的返回字典创建的作用域中。
更多信息请参见:https://security.stackexchange.com/questions/159609/how-is-it-possible-to-poison-javascript-array-constructor-and-how-does-ecmascrip?newreg=c70030debbca44248f54cec4cdf761bb

2
您需要在响应数据中包含序列化器,或者使用safe=False来实现此操作。
例如:
return JsonResponse(list_to_json, safe=False)

我认为使用序列化器时有一些新的东西,但还是谢谢。 - Projesh Bhoumik

0

这不是一个有效的字典:

{"title": , "link" : , "date": }

因为缺少值。 如果尝试添加缺失的值,则正常工作:

>>> json.dumps([{"title": "hello there", "link": "www.domain.com", "date": 2016}, {}])
'[{"link": "www.domain.com", "date": 2016, "title": "hello there"}, {}]'

我知道这个。 - shuboy2014
@shuboy2014,那你应该预料到任何语法错误都会导致程序无法正常工作。 - VHarisop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接