Ok, damit ich ein OrderedDict in json.dump
Verwenden kann. Das heißt, ein OrderedDict kann als Eingabe für JSON verwendet werden.
Aber kann es als Ausgabe verwendet werden? Wenn das so ist, wie? In meinem Fall möchte ich load
in ein OrderedDict einfügen, damit ich die Reihenfolge der Schlüssel in der Datei beibehalten kann.
Wenn nicht, gibt es eine Art Workaround?
Ja, du kannst. Durch Angabe des Arguments object_pairs_hook
Für JSONDecoder . In der Tat ist dies das genaue Beispiel in der Dokumentation.
>>> json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode('{"foo":1, "bar": 2}')
OrderedDict([('foo', 1), ('bar', 2)])
>>>
Sie können diesen Parameter an json.loads
Übergeben (falls Sie keine Decoder-Instanz für andere Zwecke benötigen):
>>> import json
>>> from collections import OrderedDict
>>> data = json.loads('{"foo":1, "bar": 2}', object_pairs_hook=OrderedDict)
>>> print json.dumps(data, indent=4)
{
"foo": 1,
"bar": 2
}
>>>
Die Verwendung von json.load
Geschieht auf die gleiche Weise:
>>> data = json.load(open('config.json'), object_pairs_hook=OrderedDict)
Einfache Version für Python 2.7+
my_ordered_dict = json.loads(json_str, object_pairs_hook=collections.OrderedDict)
Oder für Python 2.4 bis 2.6
import simplejson as json
import ordereddict
my_ordered_dict = json.loads(json_str, object_pairs_hook=ordereddict.OrderedDict)
Tolle Neuigkeiten! Seit Version 3.6 hat die cPython-Implementierung die Einfügereihenfolge von Wörterbüchern beibehalten ( https://mail.python.org/pipermail/python-dev/2016-September/146327.html ). Dies bedeutet, dass die json-Bibliothek jetzt standardmäßig die Reihenfolge beibehält. Beobachten Sie den Unterschied im Verhalten zwischen python 3.5 und 3.6. Der Code:
import json
data = json.loads('{"foo":1, "bar":2, "fiddle":{"bar":2, "foo":1}}')
print(json.dumps(data, indent=4))
In py3.5 ist die resultierende Reihenfolge undefiniert:
{
"fiddle": {
"bar": 2,
"foo": 1
},
"bar": 2,
"foo": 1
}
In der cPython-Implementierung von python 3.6:
{
"foo": 1,
"bar": 2,
"fiddle": {
"bar": 2,
"foo": 1
}
}
Die wirklich gute Nachricht ist, dass dies eine Sprachspezifikation ab python 3.7 (im Gegensatz zu einem Implementierungsdetail von cPython 3.6+) geworden ist): https: //mail.python. org/pipermail/python-dev/2017-December/151283.html
Die Antwort auf Ihre Frage lautet nun: Upgrade auf python 3.6! :)
Sie könnten die Liste der Schlüssel zusätzlich zum Dump des Diktats immer ausschreiben und dann das OrderedDict
rekonstruieren, indem Sie die Liste durchlaufen?
Zusätzlich zum Speichern der geordneten Liste der Schlüssel neben dem Wörterbuch besteht eine andere Low-Tech-Lösung, die den Vorteil hat, explizit zu sein, darin, die (geordnete) Liste der Schlüssel-Wert-Paare ordered_dict.items()
zu speichern. Laden ist ein einfaches OrderedDict(<list of key-value pairs>)
. Dies behandelt ein geordnetes Wörterbuch, obwohl JSON dieses Konzept nicht hat (JSON-Wörterbücher haben keine Reihenfolge).
Es ist in der Tat schön, die Tatsache auszunutzen, dass json
das OrderedDict in der richtigen Reihenfolge ausgibt. Es ist jedoch im Allgemeinen unnötig schwer und nicht unbedingt sinnvoll, alle JSON-Wörterbücher als OrderedDict lesen zu müssen (über object_pairs_hook
Argument), daher ist auch eine explizite Konvertierung von nur der Wörterbücher, die bestellt werden müssen, sinnvoll.
Der normalerweise verwendete Ladebefehl funktioniert, wenn Sie den Parameter object_pairs_hook angeben:
import json
from collections import OrderedDict
with open('foo.json', 'r') as fp:
metrics_types = json.load(fp, object_pairs_hook=OrderedDict)