web-dev-qa-db-fra.com

Comment convertir une liste de dictionnaires au format JSON en Python/Django?

J'ai cherché sur Google et trouvé une réponse, mais cela ne fonctionne pas pour moi. Je dois envoyer une liste sous la forme JsonResponse à Django, semblable à ceci:

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

Je convertis cela en JSON en appliquant StackOverflow question1 et question2 mais cela ne fonctionne pas pour moi. Je reçois l'erreur suivante:

Pour autoriser la sérialisation d'objets non dictés, définissez le paramètre safe sur False.

Voici mon code:

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

Jetez un coup d'oeil à la documentation

Le paramètre safe boolean est défini par défaut sur True. Si la valeur est False, tout objet peut être passé pour la sérialisation (sinon, seules les instances dict sont autorisées). Si safe est défini sur True et qu'un objet non-dict est passé en tant que premier argument, une erreur TypeError est générée.

21
The Brewmaster

Vous devez inclure des sérialiseurs ou vous pouvez le faire en utilisant safe = False pour vos données de réponse.
Comme 

return JsonResponse(list_to_json, safe=False)
1
Projesh Bhoumik

Ajouter cette réponse à ceux qui se demandent pourquoi cela n’est pas "sûr" par défaut. L'intégration d'une structure de données non dictée dans une réponse rend le service vulnérable aux attaques de piratage JSON antérieures à ES5.

Fondamentalement, avec le JSONResponse que vous utilisez ici, si un utilisateur est authentifié sur votre site, il peut maintenant récupérer cette liste d'objets {titre, lien, date} et c'est très bien. Cependant, un attaquant pourrait inclure ce point de terminaison en tant que source de script sur sa propre page malveillante (inclusion de script intersite, aussi appelée XSSI):

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

Ensuite, si un utilisateur authentifié sans méfiance accède à la page malveillante, le navigateur demandera sans le savoir le tableau de données de votre site. Comme votre service ne fait que renvoyer un tableau non attribué, l'attaquant doit également empoisonner le constructeur js Array (il s'agit de la partie de l'attaque qui a été corrigée dans ES5). Before ES5, l'attaquant pourrait simplement remplacer le constructeur Array de la manière suivante:

Array = function() {secret = this;}

Maintenant, secret contient votre liste de dictionnaires et est disponible pour le reste du script de l'attaquant, où il peut l'envoyer à son propre serveur. ES5 a résolu ce problème en forçant l'utilisation des crochets à être évaluée par le constructeur Array par défaut.

Pourquoi cela n'a-t-il jamais été un problème pour les objets du dictionnaire? Tout simplement parce que les accolades en javascript désignent une étendue isolée et que l'attaquant n'a donc aucun moyen d'injecter son propre code dans l'étendue créée par le dictionnaire renvoyé qui est entouré par des accolades.

Plus d'informations ici: https://security.stackexchange.com/questions/159609/how-is-it-possible-to-poison-javascript-array-constructor-and-how-dmas-ecmascrip?newreg=c70030debbca4424f54cdf4cdf4cb4cdf7b

0
stackPusher

Ce n'est pas un dictionnaire valide: 

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

parce que les valeurs sont manquantes . Si vous essayez d'ajouter les valeurs manquantes à la place, cela fonctionne bien:

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