2013-02-15 3 views
11
>>> raw_post_data = request.raw_post_data 
>>> print raw_post_data 
{"group":{"groupId":"2", "groupName":"GroupName"}, "members":{"1":{"firstName":"fName","lastName":"LName","address":"address"},"1": {"firstName":"f_Name","lastName":"L_Name","address":"_address"}}} 
>>> create_request = json.loads(raw_post_data) 
>>> print create_request 
{u'group': {u'groupName': u'GroupName', u'groupId': u'2'}, u'members': {u'1': {u'lastName': u'L_Name', u'firstName': u'f_Name', u'address': u'_address'}}} 

Wie Sie Mitglieder mit Schlüssel sehen ‚1‘ wird überschrieben, wenn ich json.dumps() verwendenjson.loads ermöglicht doppelte Schlüssel in einem Wörterbuch, den ersten Wert überschreiben

Gibt es eine Möglichkeit, es als Ausnahme zu fangen in Python, sagte gefunden doppelte Schlüssel in Anfrage vom Client?

+1

Zusammenhang verwenden: [simplejson Umgang mit gleichnamigen Einheiten] (http: // Stackoverflow .com/questions/7825261/simplejson-handling-of-self-named-entities) – jfs

Antwort

22

The rfc 4627 for application/json media type empfiehlt eindeutigen Schlüssel aber es macht sich nicht explizit verbieten:

Die Namen innerhalb eines Objekts sollten eindeutig sein.

Von rfc 2119:

soll dieses Wort oder das Adjektiv „Empfohlen“, bedeuten, dass es
können gute Gründe, unter bestimmten Umständen ein
bestimmtes Element zu ignorieren, aber die volle Implikationen müssen verstanden werden und
sorgfältig abgewogen werden, bevor ein anderer Kurs gewählt wird.

import json 

def dict_raise_on_duplicates(ordered_pairs): 
    """Reject duplicate keys.""" 
    d = {} 
    for k, v in ordered_pairs: 
     if k in d: 
      raise ValueError("duplicate key: %r" % (k,)) 
     else: 
      d[k] = v 
    return d 

json.loads(raw_post_data, object_pairs_hook=dict_raise_on_duplicates) 
# -> ValueError: duplicate key: u'1' 
+0

+1 Nun, es sieht viel besser :) – root

+0

Ja, das, was ich suchte .. Thx .. Allerdings json.load() Bibliothek sollte etwas bieten, das ähnliches tun könnte. –

+2

@AnujAcharya: Das Problem ist, dass es gut ist Anwendungsfälle für ein einfaches Diktat, ein "multidict", ein "multi-only-on-dups-dict", ein "raise-on-dups-dict" (mit ValueError oder KeyError?) und möglicherweise andere. Und Sie wollen genau das gleiche in 'json.loads' und' json.load' und 'csv.DictReader' und' yaml.load', und so weiter. (Siehe die aktuelle Diskussion über Python-Ideen zu 'csv'.) Sie wollen nicht alle möglichen Verhaltensweisen für alle möglichen Ladefunktionen schreiben. Und 'object_pairs_hook' scheint genau der richtige Weg zu sein, um es zu entkoppeln. – abarnert

1

Alternativ, wenn Sie alle Nachschlüssel fangen wollen (pro Level) Sie collections.Counter

from collections import Counter 

class KeyWatcher(dict): 

    def __init__(self, *args): 
     duplicates = [d for d,i in Counter([pair[0] for pair in args[0]]).items() if i > 0] 
     if duplicates: 
      raise KeyError("Can't add duplicate keys {} to a json message".format(duplicates)) 
     self.update(*args[0]) 

json.loads(raw_post_data, object_pairs_hook=KeyWatcher) 
+1

Ihr Zähler zählt die Anzahl der Vorkommen. Um also Schlüssel zu finden, die mehr als einmal vorkommen (d. H. Duplikate), sollte die Bedingung im Listenverständnis "if i> 1" und nicht "if i> 0" sein. –

+0

Auch nach dieser Korrektur scheint es immer noch nicht wie angekündigt zu funktionieren. J.F. Sebastians Code funktionierte jedoch. Ich empfehle es, es zu benutzen, auch wenn es eine gewisse Eleganz zu diesem Ansatz zu geben scheint, da es List Comprehensions anstelle von Loops verwendet. –

+0

Eine schnelle Lösung wäre 'self.update (args [0])', d. H. Ohne das Sternchen. Der KeyWatcher wird mit nur einem Argument aufgerufen, daher ist '* args' überhaupt nicht hilfreich. – VPfB

Verwandte Themen