Wie elegant unicode key in string key umwandeln?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hallo zusammen,

ich möchte Daten in einer JSON-Datei ablegen und diese bei Bedarf laden und an eine Funktion in meinem Script übergeben und zwar als Keyword-Argument.

Mein erster Anlauf endete so:

Code: Alles auswählen

In[7]: import json

In [8]: json.loads("""{"foo": "bar"}""")
Out[8]: {u'foo': u'bar'}                

In [9]: data = json.loads("""{"foo": "bar"}""")

In [10]: def foo(**kwargs):
   ....:     print kwargs  
   ....:                   
   ....:                   

In [12]: foo(**data)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/nelson/src/Python/snippets/jinja2builder/data/<ipython console> in <module>()

TypeError: foo() keywords must be strings
Der key des dicts muss also als String vorliegen - so weit eigentlich kein Problem.

Code: Alles auswählen

In [16]: foo(**{"foo": u"bar"})
{'foo': u'bar'}
Nur wie bringe ich das json-Modul dazu, genau das auch umzusetzen?

Mein Ansatz war spontan dieser:

Code: Alles auswählen

def to_str_dict(arg):
    """
    converts a dict with unicode-key based dict into a string-key based one.
    """
    new_dict = {}
    for key, value in arg.iteritems():
        new_dict[str(key)] = value
    return new_dict

def load(filename):
    try:
        with open(filename, "r") as in_file:
            # die converter Funktion an den object_hook binden
            data = json.load(in_file, object_hook=to_str_dict)
        return data
    except IOError, e:
        print e
Meine Frage ist nun: Geht das irgend wie eleganter? Oder gibt es einen komplett anderen Ansatz dazu?

Hintergrund ist ein kleines Script, das ein jinja2-Template mit Daten aus dieser JSON Datei füttern soll - quasi als simpler Template Test.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

to_str_dict kann man deutlich kürzer schreiben, ansonsten geht es nicht eleganter.

Code: Alles auswählen

def to_str_dict(d):
    return dict((str(k), v) for k, v in d.iteritems())
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Eine generelle Lösung kann es aber nicht sein, denn in der JSON-Datei könnten Attributnamen in den Objekten verwendet werden, die keine gültigen Bezeichner in Python sind. Ich denke daher, es wäre besser, das ganze JSON-Objekt in das Template hineinzureichen und nicht nur seine Attribute. Dies hier wäre ja auch gültiges JSON: `{"":null}`.

Stefan
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

sma hat geschrieben:Eine generelle Lösung kann es aber nicht sein, denn in der JSON-Datei könnten Attributnamen in den Objekten verwendet werden, die keine gültigen Bezeichner in Python sind.
Stimmt! Soll es aber auch nicht unbedingt. Es dient ja nur zur Simulation von Daten, die später vermutlich aus einer Datenbank stammen.
Ich denke daher, es wäre besser, das ganze JSON-Objekt in das Template hineinzureichen und nicht nur seine Attribute. Dies hier wäre ja auch gültiges JSON: `{"":null}`.
Das will ich eigentlich nicht unbedingt, da ich das Template ja schon möglichst "realistisch" gestalten will, sprich ich will ja bereits die gleiche Anzahl an Objekten übergeben wie später mit "richtigen" Datenobjekten.

Aber danke für den guten Hinweis :-)
Antworten