Comme le titre l'indique, j'essaie d'écrire un décodeur personnalisé pour un objet dont j'ai défini la classe et qui contient d'autres objets que j'ai définis. La classe "externe" est un Edge, défini comme suit:
class Edge:
def __init__(self, actor, movie):
self.actor = actor
self.movie = movie
def __eq__(self, other):
if (self.movie == other.movie) & (self.actor == other.actor):
return True
else:
return False
def __str__(self):
print("Actor: ", self.actor, " Movie: ", self.movie)
def get_actor(self):
return self.actor
def get_movie(self):
return self.movie
avec l'acteur et le film des classes "internes" définis comme suit:
class Movie:
def __init__(self, title, gross, soup, year):
self.title = title
self.gross = gross
self.soup = soup
self.year = year
def __eq__(self, other):
if self.title == other.title:
return True
else:
return False
def __repr__(self):
return self.title
def __str__(self):
return self.title
def get_gross(self):
return self.gross
def get_soup(self):
return self.soup
def get_title(self):
return self.title
def get_year(self):
return self.year
class Actor:
def __init__(self, name, age, soup):
self.name = name
self.age = age
self.soup = soup
def __eq__(self, other):
if self.name == other.name:
return True
else:
return False
def __repr__(self):
return self.name
def __str__(self):
return self.name
def get_age(self):
return self.age
def get_name(self):
return self.name
def get_soup(self):
return self.soup
(la soupe n'est qu'un bel objet pour la page Wikipedia de ce film/acteur, elle peut être ignorée). J'ai également écrit un encodeur client pour la classe Edge:
class EdgeEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, Edge):
return {
"Actor": {
"Name": o.get_actor().get_name(),
"Age": o.get_actor().get_age()
},
"Movie": {
"Title": o.get_movie().get_title(),
"Gross": o.get_movie().get_gross(),
"Year": o.get_movie().get_year()
}
}
return json.JSONEncoder.default(self, o)
que j'ai testé, et il sérialise correctement une liste d'arêtes dans un fichier JSON. Maintenant, mon problème survient lorsque j'essaie d'écrire un décodeur Edge. J'ai utilisé la page github ici comme référence, mais mon encodeur s'écarte du sien et je me demande s'il est nécessaire de le changer. Dois-je coder explicitement le type d'un objet comme sa propre paire clé-valeur dans sa sérialisation JSON comme il le fait, ou existe-t-il un moyen de récupérer les clés "Acteur" et "Film" avec la sérialisation du bord? De même, existe-t-il un moyen de saisir "Nom". "Age", etc., pour que je puisse reconstruire l'objet Acteur/Film, puis les utiliser pour reconstruire le bord? Y a-t-il une meilleure façon de coder mes objets à la place? J'ai également essayé de suivre le tutoriel this , mais j'ai trouvé l'utilisation de dict d'objets déroutant pour leur encodeur, et je ne savais pas comment étendre cette méthode à un objet personnalisé qui contient des objets personnalisés.
L'exemple d'encodeur/décodeur auquel vous faites référence ( ici ) pourrait être facilement étendu pour autoriser différents types d'objets dans l'entrée/sortie JSON.
Cependant, si vous souhaitez simplement qu'un décodeur simple corresponde à votre encodeur (ayant uniquement des objets Edge encodés dans votre fichier JSON), utilisez ce décodeur:
class EdgeDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
def object_hook(self, dct):
if 'Actor' in dct:
actor = Actor(dct['Actor']['Name'], dct['Actor']['Age'], '')
movie = Movie(dct['Movie']['Title'], dct['Movie']['Gross'], '', dct['Movie']['Year'])
return Edge(actor, movie)
return dct
En utilisant le code de la question pour définir les classes Movie
, Actor
, Edge
et EdgeEncoder
, le code suivant affichera un fichier de test, puis le lira de retour dans:
filename='test.json'
movie = Movie('Python', 'many dollars', '', '2000')
actor = Actor('Casper Van Dien', 49, '')
Edge = Edge(actor, movie)
with open(filename, 'w') as jsonfile:
json.dump(Edge, jsonfile, cls=EdgeEncoder)
with open(filename, 'r') as jsonfile:
Edge1 = json.load(jsonfile, cls=EdgeDecoder)
assert Edge1 == Edge