TypeError bei json.dumps({(1,1): "value"})

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
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

Hi ich habe ein Dictionary, in dem einem Tupel aus 2 Integers ein Wert zugewiesen ist:

Code: Alles auswählen

{(1,1): "value"}


Ich möchte dieses Dictionary nun gerne serialisieren, am liebsten als json-string bei diesem Versuch hier bekomme ich aber einen TypeError:

Code: Alles auswählen

import json

print json.dumps({(1,1): "value"})

Traceback (most recent call last):
  File "tsp.py", line 49, in <module>
    print json.dumps({(1,1): "value"})
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 201, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 264, in iterencode
    return _iterencode(o, 0)
TypeError: keys must be a string

Ist json tatsächlich so spezifiziert, dass Integer als Key nicht erlaubt sind?

Was gibt's für Alternativen, bzw. was würdet ihr machen:
- pickeln?
- jeweils die Integer als String en- und wieder decodieren?
- was ganz anderes?
BlackJack

@mcdwerner: Ja JSON ist tatsächlich so spezifiziert. Ist halt wie in JavaScript. Tupel gibt es auch nicht.

Bei `pickle` ist die Frage was Du damit machen willst. Einschränkungen sind: Ist auf Python beschränkt, und wenn man etwas anderes als die Grundtypen serialisiert, dann muss man immer daran denken, dass Veränderungen an Datentypen die Daten unbrauchbar machen können wenn sie derart geändert wurden, dass die gespeicherten Daten nicht mehr zum Datentyp passen.

YAML wäre vielleicht noch eine Möglichkeit. Das kennt auch keine Tupel als Schlüssel, erlaubt aber Erweiterungen des Formats, so dass zumindest Parser welche diese Erweiterungen verstehen das lesen können. Beispiel:

Code: Alles auswählen

In [24]: print yaml.dump({(1, 1): "value"})
? !!python/tuple [1, 1]
: value
Man könnte das Tupel als JSON-Liste als Zeichenkette darstellen und beim deserialisieren dann wieder zurückwandeln. Du könntest auch das Wörterbuch als Liste von Listen mit Schlüssel-Wert-Paaren serialisieren. Also in ``[[[1, 1], "value"], [[42, 23], "parrot"]]`` umwandeln und *das* dann per JSON serialisieren.
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

@BlackJack:
Danke, YAML hab ich meistens nicht "auf dem Schirm" und ich wusste auch nicht dass man das erweitern kann.

Im Moment tendiere ich eher dazu, das Tupel in einen String zu wandeln, aber wenn sich das Projekt in die Richtung tendiert , die ich gerade vermute, werde ich am Besten die Werte in squlite speichern, bei einem Anwendungsfall mit "mittlerer bis höherer Auslastung" wird das json-file 55MB groß :shock:
Antworten