[Fixed]-How to convert a list of dictionaries to JSON in Python / Django?

38đź‘Ť

âś…

return JsonResponse(list_to_json, safe=False)

Take a look at the documentation:

The safe boolean parameter defaults to True. If it’s set to False, any object can be passed for serialization (otherwise only dict instances are allowed). If safe is True and a non-dict object is passed as the first argument, a TypeError will be raised.

👤Adam Hopkins

4đź‘Ť

Adding this answer for anyone wondering why this isn’t “safe” by default. Packing a non-dict data structure into a response makes the service vulnerable to a pre-ES5 JSON Hijacking attack.

Basically, with the JSONResponse you’re using here, if a user is authenticated to your site, he can now retrieve that list of {title, link, date} objects and that’s fine. However, an attacker could include that endpoint as a script source on his own malicious page (cross site script inclusion, aka XSSI):

<script src="https://www.yourwebsite.com/secretlinks/"></script>

Then, if an unsuspecting authenticated user navigates to the malicious page, the browser will unknowingly request the array of data from your site. Since your service is just returning an unassigned array, the attacker must also poison the js Array constructor (this is the part of the attack that was fixed in ES5). Before ES5, the attacker could simply override the Array constructor like so:

Array = function() {secret = this;}

Now secret contains your list of dictionaries, and is available to the rest of the attacker’s script, where he can send it off to his own server. ES5 fixed this by forcing the use of brackets to be evaluated by the default Array constructor.

Why wasn’t this ever an issue for dictionary objects? Simply because curly brackets in javascript denote an isolated scope, and so there’s no way for the attacker to inject his own code into the scope created by the returned dictionary which is surrounded by curly brackets.

More info here: https://security.stackexchange.com/questions/159609/how-is-it-possible-to-poison-javascript-array-constructor-and-how-does-ecmascrip?newreg=c70030debbca44248f54cec4cdf761bb

👤stackPusher

2đź‘Ť

You have do include serializers or you can do this by using safe= False to your response data.
Like

return JsonResponse(list_to_json, safe=False)

0đź‘Ť

This is not a valid dictionary:

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

because the values are missing.
If you try adding the missing values instead, it works fine:

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

Leave a comment