85 votes

Désérialiser une chaîne json en un objet en python

J'ai la chaîne suivante

{"action":"print","method":"onData","data":"Madan Mohan"}

Je veux désérialiser un objet de la classe

class payload
    string action
    string method
    string data

J'utilise python 2.6 et 2.7

9voto

lovasoa Points 189

Dans les versions récentes de python, vous pouvez utiliser marshmallow-dataclass :

from marshmallow_dataclass import dataclass

@dataclass
class Payload
    action:str
    method:str
    data:str

Payload.Schema().load({"action":"print","method":"onData","data":"Madan Mohan"})

6voto

Jens Timmerman Points 1448

Je préfère ajouter une vérification des champs, par exemple pour pouvoir détecter les erreurs comme lorsque vous obtenez un json invalide, ou pas le json que vous attendiez, donc j'ai utilisé des namedtuples :

from collections import namedtuple
payload = namedtuple('payload', ['action', 'method', 'data'])
def deserialize_payload(json):
    kwargs =  dict([(field, json[field]) for field in payload._fields]) 
    return payload(**kwargs)

ceci vous permettra de recevoir de belles erreurs lorsque le json que vous analysez ne correspond pas à ce que vous voulez qu'il analyse

>>> json = {"action":"print","method":"onData","data":"Madan Mohan"}
>>> deserialize_payload(json)
payload(action='print', method='onData', data='Madan Mohan')
>>> badjson = {"error":"404","info":"page not found"}
>>> deserialize_payload(badjson)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in deserialize_payload
KeyError: 'action'

si vous souhaitez analyser des relations imbriquées, par exemple '{"parent":{"child":{"name":"henry"}}}' vous pouvez toujours utiliser les tuples nommés, et même une fonction plus réutilisable

Person = namedtuple("Person", ['parent'])
Parent = namedtuple("Parent", ['child'])
Child = namedtuple('Child', ['name'])
def deserialize_json_to_namedtuple(json, namedtuple):
    return namedtuple(**dict([(field, json[field]) for field in namedtuple._fields]))

def deserialize_person(json):
     json['parent']['child']  = deserialize_json_to_namedtuple(json['parent']['child'], Child)
     json['parent'] =  deserialize_json_to_namedtuple(json['parent'], Parent) 
     person = deserialize_json_to_namedtuple(json, Person)
     return person

en vous donnant

>>> deserialize_person({"parent":{"child":{"name":"henry"}}})
Person(parent=Parent(child=Child(name='henry')))
>>> deserialize_person({"error":"404","info":"page not found"})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in deserialize_person
KeyError: 'parent'

5voto

Sami N Points 1154

Vous pouvez spécialiser un encodeur pour la création d'objets : http://docs.python.org/2/library/json.html

import json
class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, complex):
            return {"real": obj.real,
            "imag": obj.imag,
            "__class__": "complex"}
        return json.JSONEncoder.default(self, obj)

print json.dumps(2 + 1j, cls=ComplexEncoder)

5voto

LarsVegas Points 2288

pydantique est une bibliothèque de plus en plus populaire pour les projets en Python 3.6+. Elle se charge principalement de la validation des données et de la gestion des paramètres à l'aide d'indices de type.

Un exemple de base utilisant différents types :

from pydantic import BaseModel

class ClassicBar(BaseModel):
    count_drinks: int
    is_open: bool

data = {'count_drinks': '226', 'is_open': 'False'}
cb = ClassicBar(**data)
>>> cb
ClassicBar(count_drinks=226, is_open=False)

Ce que j'aime dans le lib, c'est qu'il y a beaucoup de choses gratuites, comme par exemple

>>> cb.json()
'{"count_drinks": 226, "is_open": false}'
>>> cb.dict()
{'count_drinks': 226, 'is_open': False}

3voto

prmatta Points 1189

Une autre méthode consiste à passer la chaîne json comme un dict au constructeur de votre objet. Par exemple, votre objet est :

class Payload(object):
    def __init__(self, action, method, data, *args, **kwargs):
        self.action = action
        self.method = method
        self.data = data

Et les deux lignes de code python suivantes le construiront :

j = json.loads(yourJsonString)
payload = Payload(**j)

En fait, nous créons d'abord un objet json générique à partir de la chaîne json. Ensuite, nous passons l'objet générique json en tant que dict au constructeur de la classe Payload. Le constructeur de la classe Payload interprète le dict comme un mot-clé et définit tous les champs appropriés.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X