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
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
Pour développer la réponse de Sami :
De les docs :
class Payload(object):
def __init__(self, action, method, data):
self.action = action
self.method = method
self.data = data
import json
def as_payload(dct):
return Payload(dct['action'], dct['method'], dct['data'])
payload = json.loads(message, object_hook = as_payload)
Mon objection à la
.__dict__
La solution est que, bien qu'elle fasse le travail et qu'elle soit concise, la classe Payload devient totalement générique - il ne documente pas ses champs.
Par exemple, si le message Payload a un format inattendu, au lieu de générer une erreur de clé non trouvée lors de la création du Payload, aucune erreur ne sera générée jusqu'à ce que le Payload soit utilisé.
Si vous utilisez les indications de type de Python 3.6, vous pouvez procéder de la manière suivante :
def from_json(data, cls):
annotations: dict = cls.__annotations__ if hasattr(cls, '__annotations__') else None
if issubclass(cls, List):
list_type = cls.__args__[0]
instance: list = list()
for value in data:
instance.append(from_json(value, list_type))
return instance
elif issubclass(cls, Dict):
key_type = cls.__args__[0]
val_type = cls.__args__[1]
instance: dict = dict()
for key, value in data.items():
instance.update(from_json(key, key_type), from_json(value, val_type))
return instance
else:
instance : cls = cls()
for name, value in data.items():
field_type = annotations.get(name)
if inspect.isclass(field_type) and isinstance(value, (dict, tuple, list, set, frozenset)):
setattr(instance, name, from_json(value, field_type))
else:
setattr(instance, name, value)
return instance
Ce qui permet ensuite d'instancier des objets typés comme ceci :
class Bar:
value : int
class Foo:
x : int
bar : List[Bar]
obj : Foo = from_json(json.loads('{"x": 123, "bar":[{"value": 3}, {"value": 2}, {"value": 1}]}'), Foo)
print(obj.x)
print(obj.bar[2].value)
Cette syntaxe nécessite cependant Python 3.6 et ne couvre pas tous les cas - par exemple, le support du typage.Any... Mais au moins, elle ne pollue pas les classes qui doivent être désérialisées avec des méthodes init/tojson supplémentaires.
Je pensais perdre tous mes cheveux pour avoir résolu ce "défi". J'ai rencontré les problèmes suivants :
J'ai trouvé une bibliothèque appelée jsonpickle
qui s'est avérée très utile.
Installation :
pip install jsonpickle
Voici un exemple de code avec l'écriture d'objets imbriqués dans un fichier :
import jsonpickle
class SubObject:
def __init__(self, sub_name, sub_age):
self.sub_name = sub_name
self.sub_age = sub_age
class TestClass:
def __init__(self, name, age, sub_object):
self.name = name
self.age = age
self.sub_object = sub_object
john_junior = SubObject("John jr.", 2)
john = TestClass("John", 21, john_junior)
file_name = 'JohnWithSon' + '.json'
john_string = jsonpickle.encode(john)
with open(file_name, 'w') as fp:
fp.write(john_string)
john_from_file = open(file_name).read()
test_class_2 = jsonpickle.decode(john_from_file)
print(test_class_2.name)
print(test_class_2.age)
print(test_class_2.sub_object.sub_name)
Sortie :
John
21
John jr.
Site web : http://jsonpickle.github.io/
J'espère que cela vous fera gagner du temps (et des cheveux).
Si vous voulez économiser des lignes de code et laisser la solution la plus flexible, nous pouvons désérialiser la chaîne json en un objet dynamique :
p = lambda:None
p.__dict__ = json.loads('{"action": "print", "method": "onData", "data": "Madan Mohan"}')
>>>> p.action
output : u'print'
>>>> p.method
output : u'onData'
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.