2015-04-15 1 views
0

J'ai un peu de mal à commander ma sortie JSON. Ci-dessous est la classe Rolodex, qui contient les deux entrées de listes et les erreurs. Maintenant, la sortie est correctement formatée, comme indiqué ci-dessous, mais j'ai des problèmes avec la manière dont elle est commandée.Commander une vidage JSON par une valeur dans l'une des listes de la classe en python

class Rolodex: 
    def __init__(self): 
    self.entries = [] 
    self.errors = [] 

class Entry: 
    def __init__(self): 
    color = None 
    firstname = None 
    lastname = None 
    phonenumber = None 
    zipcode = None 

def encode_rolo(obj): 
    if isinstance(obj, Entry): 
    return obj.__dict__ 
    else: 
    raise TypeError("Unserializable object {} of type {}".format(obj,type(obj))) 

output.write(json.dumps(rolo.__dict__, sort_keys=True, indent=4, separators=(',', ': '), default=encode_rolo).encode('utf-8')) 

Voici la sortie (tronquée):

{ 
    "entries": [ 
     { 
      "color": "aqua marine", 
      "firstname": "Ria", 
      "lastname": "Tillotson", 
      "phonenumber": "196-910-5548", 
      "zipcode": "97671" 
     }, 
     { 
      "color": "blue", 
      "firstname": "Annalee", 
      "lastname": "Loftis", 
      "phonenumber": "905-329-2054", 
      "zipcode": "97296" 
     }, 
     ... 

    ], 
    "errors": [ 
     1, 
     6, 
     ... 
    ] 
} 

Comme vous pouvez le voir, les touches dans la liste des entrées sont commandés très bien. Mais je veux être en mesure de commander les entrées par (nom, prénom). Y at-il un moyen de le faire avec json.dumps?

+5

Avez-vous essayé de trier les entrées avant 'json.dumps'? – dizballanze

+0

Cela fonctionne. Que je suis bête. Le code ajouté: 'rolo.entries = trié (rolo.entries, key = attrgetter ('lastname', 'firstname'))' – mike10010100

Répondre

2

Vous pouvez l'obtenir via le tri avant la conversion en json.

Par exemple:

entries.sort(key=lambda e: e['lastname']+e['firstname']) 
+0

Alternativement: 'rolo.entries = trié (rolo.entries, key = attrgetter ('nom de famille ',' prénom ')) ' Nous vous remercions de votre aide. Pour une raison quelconque, il n'a pas cliqué que je pouvais m'assurer que la liste était triée avant de jeter à json. – mike10010100

0

Si je comprends correctement, votre problème est ici simplement que Rolodex.entries est en ordre d'insertion, et non triés par les noms que vous voulez qu'ils. Vous pouvez faire de cet attribut une propriété au lieu de l'attribut normal qu'il est actuellement, et demander au setter de trier l'attribut à chaque insertion. Voici comment:

class Rolodex(object): 
    def __init__(self): 
     self.errors = [] 
     self._entries = [] 

    @property 
    def entries(self): 
     self._entries.sort(key=lambda x: (x.lastname, x.firstname)) 
     return self._entries 

La façon dont cela fonctionne est que votre liste d'entrées est stocké dans Rolodex._entries, un attribut privé de l'instance Rolodex. Maintenant, pour que le Rolodex.entries fonctionne comme vous le souhaitez, nous en avons un property. Ce que cela signifie essentiellement, c'est que vous définissez une méthode qui doit être exécutée chaque fois que quelque chose tente d'accéder aux entrées, y compris bien sûr json.dumps(). Dans ce cas précis, nous classons la liste des entrées privées de votre classe en fonction de vos critères, puis la renvoyons juste à chaque fois que quelque chose y accède.

Notez que vous devez hériter de object avec vos classes pour que cette fonctionnalité fonctionne (ce qui est la façon dont vous utilisez new-style classes, et vous devez prendre l'habitude d'hériter toujours de object, de toute façon.)

Notez également que cette implémentation est plutôt inefficace, mais est la plus lisible et la plus facile à comprendre que je puisse trouver. Vous n'avez probablement pas besoin de meilleures performances, mais si je me trompe sur celui-ci, vous devriez regarder dans le module bisect et l'utiliser pour une insertion efficace dans votre liste, avec une méthode de réglage que vous pouvez lire dans la propriété documentation j'ai lié ci-dessus.