orjson ist eine schnelle, korrekte JSON-Bibliothek für Python. Sie gilt als die schnellste Python-Bibliothek für JSON und ist korrekter als die Standard-JSON-Bibliothek oder andere Bibliotheken von Drittanbietern. Es serialisiert Datenklassen-, Datetime-, Numpy- und UUID-Instanzen nativ.
orjson.dumps() ist etwa 10x so schnell wie json
, serialisiert gängige Typen und Untertypen, verfügt über einen default
für den Aufrufer, um anzugeben, wie beliebige Typen serialisiert werden sollen, und verfügt über eine Reihe von Flags, die die Ausgabe steuern.
orjson.loads() ist etwa doppelt so schnell wie json
und entspricht strikt UTF-8 und RFC 8259 („The JavaScript Object Notation (JSON) Data Interchange Format“).
Das Lesen und Schreiben in Dateien, zeilengetrennte JSON-Dateien usw. wird von der Bibliothek nicht bereitgestellt.
orjson unterstützt CPython 3.8, 3.9, 3.10, 3.11, 3.12, 3.13 und 3.14.
Es vertreibt amd64/x86_64-, i686/x86-, aarch64/armv8-, arm7-, POWER/ppc64le- und s390x-Räder für Linux, amd64- und aarch64-Räder für macOS sowie amd64- und i686/x86-Räder für Windows.
orjson unterstützt PyPy, eingebettete Python-Builds für Android/iOS oder PEP 554-Subinterpreter nicht und wird dies auch in Zukunft nicht tun.
Releases folgen der semantischen Versionierung und die Serialisierung eines neuen Objekttyps ohne Opt-in-Flag gilt als bahnbrechende Änderung.
orjson ist sowohl unter der Apache 2.0- als auch der MIT-Lizenz lizenziert. Das Repository und der Issue-Tracker sind github.com/ijl/orjson. Patches können dort eingereicht werden. Im Repository ist ein CHANGELOG verfügbar.
Um ein Rad von PyPI zu installieren, installieren Sie das orjson
-Paket.
Geben Sie im Format requirements.in
oder requirements.txt
Folgendes an:
orjson >= 3.10,<4
Geben Sie im pyproject.toml
-Format Folgendes an:
orjson = " ^3.10 "
Informationen zum Bau eines Rades finden Sie in der Verpackung.
Dies ist ein Beispiel für die Serialisierung mit angegebenen Optionen und die Deserialisierung:
> >> import orjson , datetime , numpy
> >> data = {
"type" : "job" ,
"created_at" : datetime . datetime ( 1970 , 1 , 1 ),
"status" : "?" ,
"payload" : numpy . array ([[ 1 , 2 ], [ 3 , 4 ]]),
}
> >> orjson . dumps ( data , option = orjson . OPT_NAIVE_UTC | orjson . OPT_SERIALIZE_NUMPY )
b'{"type":"job","created_at":"1970-01-01T00:00:00+00:00","status":" xf0 x9f x86 x97 ","payload":[[1,2],[3,4]]}'
> >> orjson . loads ( _ )
{ 'type' : 'job' , 'created_at' : '1970-01-01T00:00:00+00:00' , 'status' : '?' , 'payload' : [[ 1 , 2 ], [ 3 , 4 ]]}
orjson Version 3 serialisiert mehr Typen als Version 2. Unterklassen von str
, int
, dict
und list
werden jetzt serialisiert. Dies ist schneller und der Standardbibliothek ähnlicher. Es kann mit orjson.OPT_PASSTHROUGH_SUBCLASS
deaktiviert werden. dataclasses.dataclass
Instanzen werden jetzt standardmäßig serialisiert und können nicht in einer default
angepasst werden, es sei denn, option=orjson.OPT_PASSTHROUGH_DATACLASS
ist angegeben. uuid.UUID
Instanzen werden standardmäßig serialisiert. Für jeden Typ, der jetzt serialisiert ist, können Implementierungen in einer default
und Optionen, die sie ermöglichen, entfernt werden, müssen es aber nicht. Bei der Deserialisierung gab es keine Änderung.
Bei der Migration von der Standardbibliothek besteht der größte Unterschied darin, dass orjson.dumps
bytes
und json.dumps
einen str
zurückgibt.
Benutzer mit dict
, die Nicht- str
-Schlüssel verwenden, sollten option=orjson.OPT_NON_STR_KEYS
angeben.
sort_keys
wird durch option=orjson.OPT_SORT_KEYS
ersetzt.
indent
wird durch option=orjson.OPT_INDENT_2
ersetzt und andere Einrückungsebenen werden nicht unterstützt.
ensure_ascii
ist heute wahrscheinlich nicht mehr relevant und UTF-8-Zeichen können nicht in ASCII maskiert werden.
def dumps (
__obj : Any ,
default : Optional [ Callable [[ Any ], Any ]] = ...,
option : Optional [ int ] = ...,
) -> bytes : ...
dumps()
serialisiert Python-Objekte in JSON.
Es serialisiert nativ str
, dict
, list
, tuple
, int
, float
, bool
, None
, dataclasses.dataclass
, typing.TypedDict
, datetime.datetime
, datetime.date
, datetime.time
, uuid.UUID
, numpy.ndarray
und orjson.Fragment
. Es unterstützt default
beliebige Typen. Es serialisiert Unterklassen von str
, int
, dict
, list
, dataclasses.dataclass
und enum.Enum
. Unterklassen von tuple
werden nicht serialisiert, um zu vermeiden, dass namedtuple
Tupelobjekte als Arrays serialisiert werden. Um die Serialisierung von Unterklassen zu vermeiden, geben Sie die Option orjson.OPT_PASSTHROUGH_SUBCLASS
an.
Die Ausgabe ist ein bytes
Objekt mit UTF-8.
Die globale Dolmetschersperre (GIL) wird für die Dauer des Anrufs gehalten.
Es löst JSONEncodeError
für einen nicht unterstützten Typ aus. Diese Ausnahmemeldung beschreibt das ungültige Objekt mit der Fehlermeldung Type is not JSON serializable: ...
. Um dies zu beheben, geben Sie den Standardwert an.
Es löst JSONEncodeError
für einen str
aus, der ungültiges UTF-8 enthält.
Es löst JSONEncodeError
bei einer Ganzzahl aus, die standardmäßig 64 Bit oder mit OPT_STRICT_INTEGER
53 Bit überschreitet.
Es löst JSONEncodeError
aus, wenn ein dict
einen Schlüssel eines anderen Typs als str
hat, es sei denn, OPT_NON_STR_KEYS
ist angegeben.
Es löst JSONEncodeError
aus, wenn die Standardausgabe auf die default
Verarbeitung mit default
Tiefe von mehr als 254 Ebenen zurückgreift.
Es löst JSONEncodeError
bei Zirkelverweisen aus.
Es löst JSONEncodeError
aus, wenn eine tzinfo
für ein Datetime-Objekt nicht unterstützt wird.
JSONEncodeError
ist eine Unterklasse von TypeError
. Dies dient der Kompatibilität mit der Standardbibliothek.
Wenn der Fehler default
durch eine Ausnahme verursacht wurde, verkettet JSONEncodeError
die ursprüngliche Ausnahme als __cause__
.
Um eine Unterklasse oder beliebige Typen zu serialisieren, geben Sie default
als aufrufbares Element an, das einen unterstützten Typ zurückgibt. default
kann eine Funktion, ein Lambda oder eine aufrufbare Klasseninstanz sein. Um anzugeben, dass ein Typ nicht default
behandelt wurde, lösen Sie eine Ausnahme wie TypeError
aus.
> >> import orjson , decimal
> >>
def default ( obj ):
if isinstance ( obj , decimal . Decimal ):
return str ( obj )
raise TypeError
> >> orjson . dumps ( decimal . Decimal ( "0.0842389659712649442845" ))
JSONEncodeError : Type is not JSON serializable : decimal . Decimal
> >> orjson . dumps ( decimal . Decimal ( "0.0842389659712649442845" ), default = default )
b'"0.0842389659712649442845"'
> >> orjson . dumps ({ 1 , 2 }, default = default )
orjson . JSONEncodeError : Type is not JSON serializable : set
Das default
aufrufbare Objekt kann ein Objekt zurückgeben, das selbst bis zu 254 Mal default
behandelt werden muss, bevor eine Ausnahme ausgelöst wird.
Es ist wichtig, dass default
eine Ausnahme ausgelöst wird, wenn ein Typ nicht verarbeitet werden kann. Andernfalls gibt Python implizit None
zurück, was dem Aufrufer wie ein legitimer Wert erscheint und serialisiert ist:
> >> import orjson , json
> >>
def default ( obj ):
if isinstance ( obj , decimal . Decimal ):
return str ( obj )
> >> orjson . dumps ({ "set" :{ 1 , 2 }}, default = default )
b'{"set":null}'
> >> json . dumps ({ "set" :{ 1 , 2 }}, default = default )
'{"set":null}'
Um zu ändern, wie Daten serialisiert werden, geben Sie option
an. Jede option
ist eine ganzzahlige Konstante in orjson
. Um mehrere Optionen anzugeben, maskieren Sie sie gemeinsam, z. B. option=orjson.OPT_STRICT_INTEGER | orjson.OPT_NAIVE_UTC
.
Hängen Sie n
an die Ausgabe an. Dies dient der Bequemlichkeit und Optimierung des Musters dumps(...) + "n"
. bytes
Objekte sind unveränderlich und dieses Muster kopiert den ursprünglichen Inhalt.
> >> import orjson
> >> orjson . dumps ([])
b"[]"
> >> orjson . dumps ([], option = orjson . OPT_APPEND_NEWLINE )
b"[] n "
Schön gedruckte Ausgabe mit einem Einzug von zwei Leerzeichen. Dies entspricht indent=2
in der Standardbibliothek. Pretty-Druck ist langsamer und die Ausgabe größer. orjson ist im Vergleich die schnellste Bibliothek im Pretty-Printing und verlangsamt den Pretty-Print deutlich weniger als die Standardbibliothek. Diese Option ist mit allen anderen Optionen kompatibel.
> >> import orjson
> >> orjson . dumps ({ "a" : "b" , "c" : { "d" : True }, "e" : [ 1 , 2 ]})
b'{"a":"b","c":{"d":true},"e":[1,2]}'
> >> orjson . dumps (
{ "a" : "b" , "c" : { "d" : True }, "e" : [ 1 , 2 ]},
option = orjson . OPT_INDENT_2
)
b'{ n "a": "b", n "c": { n "d": true n }, n "e": [ n 1, n 2 n ] n }'
Wenn sie angezeigt werden, sehen die Einrückungen und Zeilenumbrüche folgendermaßen aus:
{
"a" : " b " ,
"c" : {
"d" : true
},
"e" : [
1 ,
2
]
}
Dies misst die Serialisierung des github.json-Fixtures als kompakt (52 KiB) oder hübsch (64 KiB):
Bibliothek | kompakt (ms) | hübsch (ms) | vs. orjson |
---|---|---|---|
orjson | 0,01 | 0,02 | 1 |
json | 0,13 | 0,54 | 34 |
Dies misst die Serialisierung des citm_catalog.json-Fixtures, was aufgrund der Menge an Verschachtelungen und Zeilenumbrüchen eher ein Worst-Case ist, als kompakt (489 KiB) oder hübsch (1,1 MiB):
Bibliothek | kompakt (ms) | hübsch (ms) | vs. orjson |
---|---|---|---|
orjson | 0,25 | 0,45 | 1 |
json | 3.01 | 24.42 | 54.4 |
Dies kann mit dem pyindent
-Skript reproduziert werden.
Serialisieren Sie datetime.datetime
Objekte ohne tzinfo
als UTC. Dies hat keine Auswirkungen auf datetime.datetime
-Objekte, für die tzinfo
festgelegt ist.
> >> import orjson , datetime
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 ),
)
b'"1970-01-01T00:00:00"'
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 ),
option = orjson . OPT_NAIVE_UTC ,
)
b'"1970-01-01T00:00:00+00:00"'
dict
eines anderen Typs als str
serialisieren. Dadurch können dict
str
, int
, float
, bool
, None
, datetime.datetime
, datetime.date
, datetime.time
, enum.Enum
und uuid.UUID
sein. Zum Vergleich serialisiert die Standardbibliothek standardmäßig str
, int
, float
, bool
oder None
. Orjson-Benchmarks sind schneller bei der Serialisierung von Nicht- str
-Schlüsseln als andere Bibliotheken. Diese Option ist für str
-Tasten langsamer als die Standardeinstellung.
> >> import orjson , datetime , uuid
> >> orjson . dumps (
{ uuid . UUID ( "7202d115-7ff3-4c81-a7c1-2a1f067b1ece" ): [ 1 , 2 , 3 ]},
option = orjson . OPT_NON_STR_KEYS ,
)
b'{"7202d115-7ff3-4c81-a7c1-2a1f067b1ece":[1,2,3]}'
> >> orjson . dumps (
{ datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 ): [ 1 , 2 , 3 ]},
option = orjson . OPT_NON_STR_KEYS | orjson . OPT_NAIVE_UTC ,
)
b'{"1970-01-01T00:00:00+00:00":[1,2,3]}'
Diese Typen werden im Allgemeinen so serialisiert, wie sie als Werte wären, z. B. datetime.datetime
ist immer noch ein RFC 3339-String und berücksichtigt Optionen, die ihn beeinflussen. Die Ausnahme besteht darin, dass int
-Serialisierung OPT_STRICT_INTEGER
nicht berücksichtigt.
Bei dieser Option besteht das Risiko, dass doppelte Schlüssel entstehen. Dies liegt daran, dass Nicht str
-Objekte möglicherweise in denselben str
serialisiert werden wie ein vorhandener Schlüssel, z. B. {"1": true, 1: false}
. Der letzte Schlüssel, der in das dict
eingefügt wird, wird zuletzt serialisiert und ein JSON-Deserialisierer nimmt vermutlich das letzte Vorkommen eines Schlüssels (im obigen Beispiel false
). Der erste Wert geht verloren.
Diese Option ist mit orjson.OPT_SORT_KEYS
kompatibel. Beachten Sie bei Verwendung der Sortierung, dass die Sortierung instabil und bei doppelten Schlüsseln unvorhersehbar ist.
> >> import orjson , datetime
> >> orjson . dumps (
{ "other" : 1 , datetime . date ( 1970 , 1 , 5 ): 2 , datetime . date ( 1970 , 1 , 3 ): 3 },
option = orjson . OPT_NON_STR_KEYS | orjson . OPT_SORT_KEYS
)
b'{"1970-01-03":3,"1970-01-05":2,"other":1}'
Dies misst die Serialisierung von 589 KB JSON, bestehend aus einer list
von 100 dict
, in denen jedes dict
sowohl 365 zufällig sortierte int
-Schlüssel, die Epochenzeitstempel darstellen, als auch einen str
-Schlüssel enthält und der Wert für jeden Schlüssel eine einzelne Ganzzahl ist. In „str-Schlüsseln“ wurden die Schlüssel vor der Serialisierung in str
konvertiert, und orjson gibt immer noch option=orjson.OPT_NON_STR_KEYS
an (was immer etwas langsamer ist).
Bibliothek | str-Tasten (ms) | int-Schlüssel (ms) | int Schlüssel sortiert (ms) |
---|---|---|---|
orjson | 0,5 | 0,93 | 2.08 |
json | 2,72 | 3,59 |
json ist leer, da es TypeError
auslöst, wenn versucht wird, zu sortieren, bevor alle Schlüssel in str
konvertiert werden. Dies kann mit dem pynonstr
-Skript reproduziert werden.
Serialisieren Sie das microsecond
nicht für datetime.datetime
und datetime.time
Instanzen.
> >> import orjson , datetime
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 , 1 ),
)
b'"1970-01-01T00:00:00.000001"'
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 , 1 ),
option = orjson . OPT_OMIT_MICROSECONDS ,
)
b'"1970-01-01T00:00:00"'
Übergeben Sie dataclasses.dataclass
-Instanzen an default
. Dies ermöglicht die Anpassung der Ausgabe, ist jedoch viel langsamer.
> >> import orjson , dataclasses
> >>
@ dataclasses . dataclass
class User :
id : str
name : str
password : str
def default ( obj ):
if isinstance ( obj , User ):
return { "id" : obj . id , "name" : obj . name }
raise TypeError
> >> orjson . dumps ( User ( "3b1" , "asd" , "zxc" ))
b'{"id":"3b1","name":"asd","password":"zxc"}'
> >> orjson . dumps ( User ( "3b1" , "asd" , "zxc" ), option = orjson . OPT_PASSTHROUGH_DATACLASS )
TypeError : Type is not JSON serializable : User
> >> orjson . dumps (
User ( "3b1" , "asd" , "zxc" ),
option = orjson . OPT_PASSTHROUGH_DATACLASS ,
default = default ,
)
b'{"id":"3b1","name":"asd"}'
Übergeben Sie die Instanzen datetime.datetime
, datetime.date
und datetime.time
an default
. Dies ermöglicht die Serialisierung von Datumsangaben in ein benutzerdefiniertes Format, z. B. HTTP-Daten:
> >> import orjson , datetime
> >>
def default ( obj ):
if isinstance ( obj , datetime . datetime ):
return obj . strftime ( "%a, %d %b %Y %H:%M:%S GMT" )
raise TypeError
> >> orjson . dumps ({ "created_at" : datetime . datetime ( 1970 , 1 , 1 )})
b'{"created_at":"1970-01-01T00:00:00"}'
> >> orjson . dumps ({ "created_at" : datetime . datetime ( 1970 , 1 , 1 )}, option = orjson . OPT_PASSTHROUGH_DATETIME )
TypeError : Type is not JSON serializable : datetime . datetime
> >> orjson . dumps (
{ "created_at" : datetime . datetime ( 1970 , 1 , 1 )},
option = orjson . OPT_PASSTHROUGH_DATETIME ,
default = default ,
)
b'{"created_at":"Thu, 01 Jan 1970 00:00:00 GMT"}'
Dies wirkt sich nicht auf Datums- und Uhrzeitangaben in dict
aus, wenn OPT_NON_STR_KEYS verwendet wird.
Passthrough-Unterklassen integrierter Typen an default
.
> >> import orjson
> >>
class Secret ( str ):
pass
def default ( obj ):
if isinstance ( obj , Secret ):
return "******"
raise TypeError
> >> orjson . dumps ( Secret ( "zxc" ))
b'"zxc"'
> >> orjson . dumps ( Secret ( "zxc" ), option = orjson . OPT_PASSTHROUGH_SUBCLASS )
TypeError : Type is not JSON serializable : Secret
> >> orjson . dumps ( Secret ( "zxc" ), option = orjson . OPT_PASSTHROUGH_SUBCLASS , default = default )
b'"******"'
Dies hat keine Auswirkungen auf die Serialisierung von Unterklassen als dict
, wenn OPT_NON_STR_KEYS verwendet wird.
Dies ist veraltet und hat in Version 3 keine Auswirkungen. In Version 2 war dies erforderlich, um dataclasses.dataclass
Instanzen zu serialisieren. Weitere Informationen finden Sie unter Datenklasse.
numpy.ndarray
Instanzen serialisieren. Weitere Informationen finden Sie unter Numpy.
Dies ist veraltet und hat in Version 3 keine Auswirkungen. In Version 2 war dies erforderlich, um uuid.UUID
Instanzen zu serialisieren. Weitere Informationen finden Sie unter UUID.
dict
in sortierter Reihenfolge serialisieren. Standardmäßig wird in einer nicht festgelegten Reihenfolge serialisiert. Dies entspricht sort_keys=True
in der Standardbibliothek.
Dies kann verwendet werden, um sicherzustellen, dass die Reihenfolge für Hashing oder Tests deterministisch ist. Es hat erhebliche Leistungseinbußen zur Folge und wird im Allgemeinen nicht empfohlen.
> >> import orjson
> >> orjson . dumps ({ "b" : 1 , "c" : 2 , "a" : 3 })
b'{"b":1,"c":2,"a":3}'
> >> orjson . dumps ({ "b" : 1 , "c" : 2 , "a" : 3 }, option = orjson . OPT_SORT_KEYS )
b'{"a":3,"b":1,"c":2}'
Dies misst die unsortierte und sortierte Serialisierung des twitter.json-Fixtures:
Bibliothek | unsortiert (ms) | sortiert (ms) | vs. orjson |
---|---|---|---|
orjson | 0,11 | 0,3 | 1 |
json | 1,36 | 1,93 | 6.4 |
Der Benchmark kann mit dem pysort
-Skript reproduziert werden.
Die Sortierung berücksichtigt nicht die Sortierung/das Gebietsschema:
> >> import orjson
> >> orjson . dumps ({ "a" : 1 , "ä" : 2 , "A" : 3 }, option = orjson . OPT_SORT_KEYS )
b'{"A":3,"a":1," xc3 xa4 ":2}'
Dies ist das gleiche Sortierverhalten wie bei der Standardbibliothek.
dataclass
werden auch als Karten serialisiert, dies hat jedoch keine Auswirkungen auf sie.
Erzwingen Sie eine 53-Bit-Beschränkung für Ganzzahlen. Ansonsten liegt die Grenze bei 64 Bit, genau wie bei der Python-Standardbibliothek. Weitere Informationen finden Sie unter int.
Serialisieren Sie eine UTC-Zeitzone auf datetime.datetime
-Instanzen als Z
statt +00:00
.
> >> import orjson , datetime , zoneinfo
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 , tzinfo = zoneinfo . ZoneInfo ( "UTC" )),
)
b'"1970-01-01T00:00:00+00:00"'
> >> orjson . dumps (
datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 , tzinfo = zoneinfo . ZoneInfo ( "UTC" )),
option = orjson . OPT_UTC_Z
)
b'"1970-01-01T00:00:00Z"'
orjson.Fragment
schließt bereits serialisiertes JSON in ein Dokument ein. Dies ist eine effiziente Möglichkeit, JSON-Blobs aus einem Cache, einem JSONB-Feld oder einem separat serialisierten Objekt einzubinden, ohne zuvor über loads()
in Python-Objekte deserialisieren zu müssen.
> >> import orjson
> >> orjson . dumps ({ "key" : "zxc" , "data" : orjson . Fragment ( b'{"a": "b", "c": 1}' )})
b'{"key":"zxc","data":{"a": "b", "c": 1}}'
Es erfolgt keine Neuformatierung: orjson.OPT_INDENT_2
wirkt sich weder auf einen kompakten Blob aus, noch wird ein hübsch gedruckter JSON-Blob als kompakt umgeschrieben.
Die Eingabe muss bytes
oder str
sein und als Positionsargument angegeben werden.
Dies löst orjson.JSONEncodeError
aus, wenn ein str
angegeben wird und die Eingabe kein gültiges UTF-8 ist. Andernfalls erfolgt keine Validierung und es ist möglich, ungültiges JSON zu schreiben. Dies sind keine Escape-Zeichen. Es wurde getestet, dass die Implementierung nicht abstürzt, wenn ungültige Zeichenfolgen oder ungültiges JSON angegeben werden.
def loads ( __obj : Union [ bytes , bytearray , memoryview , str ]) -> Any : ...
loads()
deserialisiert JSON in Python-Objekte. Es deserialisiert in dict
, list
, int
, float
, str
, bool
und None
Objekte.
bytes
, bytearray
, memoryview
und str
Eingaben werden akzeptiert. Wenn die Eingabe als Objekt memoryview
, bytearray
oder bytes
vorliegt, wird empfohlen, diese direkt zu übergeben, anstatt ein unnötiges str
Objekt zu erstellen. Das heißt, orjson.loads(b"{}")
anstelle von orjson.loads(b"{}".decode("utf-8"))
. Dies hat eine geringere Speichernutzung und eine geringere Latenz zur Folge.
Die Eingabe muss gültiges UTF-8 sein.
orjson verwaltet für die Dauer des Prozesses einen Cache mit Kartenschlüsseln. Dies führt zu einer Nettoreduzierung der Speichernutzung, da doppelte Zeichenfolgen vermieden werden. Die Schlüssel dürfen höchstens 64 Byte groß sein, um zwischengespeichert zu werden, und es werden 2048 Einträge gespeichert.
Die globale Dolmetschersperre (GIL) wird für die Dauer des Anrufs gehalten.
Es löst JSONDecodeError
aus, wenn ein ungültiger Typ oder ungültiges JSON angegeben wird. Dies gilt auch, wenn die Eingabe NaN
, Infinity
oder -Infinity
enthält, was die Standardbibliothek zulässt, aber kein gültiges JSON ist.
Es löst JSONDecodeError
aus, wenn eine Kombination aus Array oder Objekt 1024 Ebenen tief rekursiv ist.
JSONDecodeError
ist eine Unterklasse von json.JSONDecodeError
und ValueError
. Dies dient der Kompatibilität mit der Standardbibliothek.
orjson serialisiert Instanzen von dataclasses.dataclass
nativ. Es serialisiert Instanzen 40–50-mal so schnell wie andere Bibliotheken und vermeidet eine starke Verlangsamung, die bei anderen Bibliotheken im Vergleich zur Serialisierung dict
auftritt.
Es wird unterstützt, alle Varianten von Datenklassen zu übergeben, einschließlich Datenklassen, die __slots__
verwenden, eingefrorene Datenklassen, solche mit optionalen oder Standardattributen und Unterklassen. Es gibt einen Leistungsvorteil, wenn man __slots__
nicht verwendet.
Bibliothek | Diktat (ms) | Datenklasse (ms) | vs. orjson |
---|---|---|---|
orjson | 0,43 | 0,95 | 1 |
json | 5,81 | 38.32 | 40 |
Dies misst die Serialisierung von 555 KB von JSON, orjson nativ und anderen Bibliotheken unter Verwendung default
zur Serialisierung der Ausgabe von dataclasses.asdict()
. Dies kann mit dem pydataclass
-Skript reproduziert werden.
Datenklassen werden als Karten serialisiert, wobei jedes Attribut in der bei der Klassendefinition angegebenen Reihenfolge serialisiert wird:
> >> import dataclasses , orjson , typing
@ dataclasses . dataclass
class Member :
id : int
active : bool = dataclasses . field ( default = False )
@ dataclasses . dataclass
class Object :
id : int
name : str
members : typing . List [ Member ]
> >> orjson . dumps ( Object ( 1 , "a" , [ Member ( 1 , True ), Member ( 2 )]))
b'{"id":1,"name":"a","members":[{"id":1,"active":true},{"id":2,"active":false}]}'
orjson serialisiert datetime.datetime
Objekte in das RFC 3339-Format, z. B. „1970-01-01T00:00:00+00:00“. Dies ist eine Teilmenge von ISO 8601 und kompatibel mit isoformat()
in der Standardbibliothek.
> >> import orjson , datetime , zoneinfo
> >> orjson . dumps (
datetime . datetime ( 2018 , 12 , 1 , 2 , 3 , 4 , 9 , tzinfo = zoneinfo . ZoneInfo ( "Australia/Adelaide" ))
)
b'"2018-12-01T02:03:04.000009+10:30"'
> >> orjson . dumps (
datetime . datetime ( 2100 , 9 , 1 , 21 , 55 , 2 ). replace ( tzinfo = zoneinfo . ZoneInfo ( "UTC" ))
)
b'"2100-09-01T21:55:02+00:00"'
> >> orjson . dumps (
datetime . datetime ( 2100 , 9 , 1 , 21 , 55 , 2 )
)
b'"2100-09-01T21:55:02"'
datetime.datetime
unterstützt Instanzen mit einer tzinfo
, die None
, datetime.timezone.utc
, eine Zeitzoneninstanz aus dem zoneinfo
Modul von Python3.9+ oder eine Zeitzoneninstanz aus den pendulum
, pytz
oder dateutil
/ arrow
-Bibliotheken von Drittanbietern ist.
Für Zeitzonen ist es am schnellsten, die zoneinfo.ZoneInfo
der Standardbibliothek zu verwenden.
datetime.time
Objekte dürfen kein tzinfo
haben.
> >> import orjson , datetime
> >> orjson . dumps ( datetime . time ( 12 , 0 , 15 , 290 ))
b'"12:00:15.000290"'
datetime.date
Objekte werden immer serialisiert.
> >> import orjson , datetime
> >> orjson . dumps ( datetime . date ( 1900 , 1 , 2 ))
b'"1900-01-02"'
Fehler mit tzinfo
führen dazu, dass JSONEncodeError
ausgelöst wird.
Um die Serialisierung von datetime
-Objekten zu deaktivieren, geben Sie die Option orjson.OPT_PASSTHROUGH_DATETIME
an.
Um das Suffix „Z“ anstelle von „+00:00“ zur Angabe der UTC-Zeit („Zulu“) zu verwenden, verwenden Sie die Option orjson.OPT_UTC_Z
.
Um davon auszugehen, dass Datumsangaben ohne Zeitzone UTC sind, verwenden Sie die Option orjson.OPT_NAIVE_UTC
.
orjson serialisiert Aufzählungen nativ. Optionen gelten für ihre Werte.
> >> import enum , datetime , orjson
> >>
class DatetimeEnum ( enum . Enum ):
EPOCH = datetime . datetime ( 1970 , 1 , 1 , 0 , 0 , 0 )
> >> orjson . dumps ( DatetimeEnum . EPOCH )
b'"1970-01-01T00:00:00"'
> >> orjson . dumps ( DatetimeEnum . EPOCH , option = orjson . OPT_NAIVE_UTC )
b'"1970-01-01T00:00:00+00:00"'
Aufzählungen mit Mitgliedern, die keine unterstützten Typen sind, können mit default
serialisiert werden:
> >> import enum , orjson
> >>
class Custom :
def __init__ ( self , val ):
self . val = val
def default ( obj ):
if isinstance ( obj , Custom ):
return obj . val
raise TypeError
class CustomEnum ( enum . Enum ):
ONE = Custom ( 1 )
> >> orjson . dumps ( CustomEnum . ONE , default = default )
b'1'
orjson serialisiert und deserialisiert Gleitkommazahlen mit doppelter Genauigkeit ohne Präzisionsverlust und konsistente Rundung.
orjson.dumps()
serialisiert Nan, Infinity und -Infinity, die nicht JSON-konform sind, als null
:
> >> import orjson , json
> >> orjson . dumps ([ float ( "NaN" ), float ( "Infinity" ), float ( "-Infinity" )])
b'[null,null,null]'
> >> json . dumps ([ float ( "NaN" ), float ( "Infinity" ), float ( "-Infinity" )])
'[NaN, Infinity, -Infinity]'
orjson serialisiert und deserialisiert standardmäßig 64-Bit-Ganzzahlen. Der unterstützte Bereich reicht vom Minimum einer vorzeichenbehafteten 64-Bit-Ganzzahl (-9223372036854775807) bis zum Maximum einer vorzeichenlosen 64-Bit-Ganzzahl (18446744073709551615). Dies ist weitgehend kompatibel, es gibt jedoch Implementierungen, die nur 53-Bit für Ganzzahlen unterstützen, z. B. Webbrowser. Für diese Implementierungen kann dumps()
so konfiguriert werden, dass bei Werten, die den 53-Bit-Bereich überschreiten, ein JSONEncodeError
ausgelöst wird.
> >> import orjson
> >> orjson . dumps ( 9007199254740992 )
b'9007199254740992'
> >> orjson . dumps ( 9007199254740992 , option = orjson . OPT_STRICT_INTEGER )
JSONEncodeError : Integer exceeds 53 - bit range
>> > orjson . dumps ( - 9007199254740992 , option = orjson . OPT_STRICT_INTEGER )
JSONEncodeError : Integer exceeds 53 - bit range
orjson serialisiert numpy.ndarray
und einzelne numpy.float64
, numpy.float32
, numpy.float16
( numpy.half
), numpy.int64
, numpy.int32
, numpy.int16
, numpy.int8
, numpy.uint64
, numpy.uint32
, numpy.uint16
, numpy.uint8
, numpy.uintp
, numpy.intp
, numpy.datetime64
und numpy.bool
Instanzen.
orjson ist sowohl mit Numpy v1 als auch mit v2 kompatibel.
orjson ist bei der Serialisierung von Numpy-Instanzen schneller als alle verglichenen Bibliotheken. Für die Serialisierung von Numpy-Daten muss option=orjson.OPT_SERIALIZE_NUMPY
angegeben werden.
> >> import orjson , numpy
> >> orjson . dumps (
numpy . array ([[ 1 , 2 , 3 ], [ 4 , 5 , 6 ]]),
option = orjson . OPT_SERIALIZE_NUMPY ,
)
b'[[1,2,3],[4,5,6]]'
Das Array muss ein zusammenhängendes C-Array ( C_CONTIGUOUS
) und einer der unterstützten Datentypen sein.
Beachten Sie einen Unterschied zwischen der Serialisierung numpy.float32
mit ndarray.tolist()
oder orjson.dumps(..., option=orjson.OPT_SERIALIZE_NUMPY)
: tolist()
wird vor der Serialisierung in ein double
konvertiert, der native Pfad von orjson jedoch nicht. Dadurch kann es zu unterschiedlichen Rundungen kommen.
numpy.datetime64
-Instanzen werden serialisiert, da RFC 3339-Strings und Datetime-Optionen sie beeinflussen.
> >> import orjson , numpy
> >> orjson . dumps (
numpy . datetime64 ( "2021-01-01T00:00:00.172" ),
option = orjson . OPT_SERIALIZE_NUMPY ,
)
b'"2021-01-01T00:00:00.172000"'
> >> orjson . dumps (
numpy . datetime64 ( "2021-01-01T00:00:00.172" ),
option = (
orjson . OPT_SERIALIZE_NUMPY |
orjson . OPT_NAIVE_UTC |
orjson . OPT_OMIT_MICROSECONDS
),
)
b'"2021-01-01T00:00:00+00:00"'
Wenn ein Array kein zusammenhängendes C-Array ist, einen nicht unterstützten Datentyp enthält oder ein numpy.datetime64
mit einer nicht unterstützten Darstellung (z. B. Pikosekunden) enthält, fällt orjson auf default
zurück. default
kann obj.tolist()
angegeben werden.
Wenn ein Array nicht im nativen Endian-Format vorliegt, z. B. ein Array von Big-Endian-Werten auf einem Little-Endian-System, wird orjson.JSONEncodeError
ausgelöst.
Wenn ein Array fehlerhaft ist, wird orjson.JSONEncodeError
ausgelöst.
Dies misst die Serialisierung von 92 MB JSON aus einem numpy.ndarray
mit den Dimensionen (50000, 100)
und numpy.float64
-Werten:
Bibliothek | Latenz (ms) | RSS-Diff (MiB) | vs. orjson |
---|---|---|---|
orjson | 105 | 105 | 1 |
json | 1.481 | 295 | 14.2 |
Dies misst die Serialisierung von 100 MB JSON aus einem numpy.ndarray
mit den Dimensionen (100000, 100)
und numpy.int32
Werten:
Bibliothek | Latenz (ms) | RSS-Diff (MiB) | vs. orjson |
---|---|---|---|
orjson | 68 | 119 | 1 |
json | 684 | 501 | 10.1 |
Dies misst die Serialisierung von 105 MB JSON aus einem numpy.ndarray
mit den Dimensionen (100000, 200)
und numpy.bool
-Werten:
Bibliothek | Latenz (ms) | RSS-Diff (MiB) | vs. orjson |
---|---|---|---|
orjson | 50 | 125 | 1 |
json | 573 | 398 | 11.5 |
In diesen Benchmarks serialisiert orjson nativ und json
serialisiert ndarray.tolist()
per default
. Die RSS-Spalte misst die maximale Speichernutzung während der Serialisierung. Dies kann mit dem pynumpy
-Skript reproduziert werden.
orjson hat keine Installations- oder Kompilierungsabhängigkeit von Numpy. Die Implementierung ist unabhängig und liest numpy.ndarray
mit PyArrayInterface
.
orjson legt großen Wert auf die UTF-8-Konformität. Dies ist strenger als das JSON-Modul der Standardbibliothek, das UTF-16-Ersatzzeichen serialisiert und deserialisiert, z. B. „ud800“, die ungültiges UTF-8 sind.
Wenn orjson.dumps()
eine str
angegeben wird, die kein gültiges UTF-8 enthält, wird orjson.JSONEncodeError
ausgelöst. Wenn loads()
ungültiges UTF-8 empfängt, wird orjson.JSONDecodeError
ausgelöst.
> >> import orjson , json
> >> orjson . dumps ( ' ud800 ' )
JSONEncodeError : str is not valid UTF - 8 : surrogates not allowed
>> > json . dumps ( ' ud800 ' )
'" \ ud800"'
> >> orjson . loads ( '" \ ud800"' )
JSONDecodeError : unexpected end of hex escape at line 1 column 8 : line 1 column 1 ( char 0 )
> >> json . loads ( '" \ ud800"' )
' ud800 '
Um fehlerhafte Eingaben bestmöglich zu deserialisieren, dekodieren Sie zunächst bytes
mit dem Argument replace
oder lossy
für errors
:
> >> import orjson
> >> orjson . loads ( b'" xed xa0 x80 "' )
JSONDecodeError : str is not valid UTF - 8 : surrogates not allowed
>> > orjson . loads ( b'" xed xa0 x80 "' . decode ( "utf-8" , "replace" ))
'���'
orjson serialisiert uuid.UUID
Instanzen in das RFC 4122-Format, z. B. „f81d4fae-7dec-11d0-a765-00a0c91e6bf6“.
> >> import orjson , uuid
> >> orjson . dumps ( uuid . uuid5 ( uuid . NAMESPACE_DNS , "python.org" ))
b'"886313e1-3b8a-5372-9b90-0c9aee199e5d"'
Die Bibliothek verfügt über umfassende Tests. Es gibt Tests gegen Fixtures in den Repositorys JSONTestSuite und nativejson-benchmark. Es wurde getestet, dass es nicht mit der Big List of Naughty Strings kollidiert. Es wurde getestet, dass kein Speicher verloren geht. Es wurde darauf getestet, dass es nicht abstürzt und ungültiges UTF-8 nicht akzeptiert. Es gibt Integrationstests, die die Verwendung der Bibliothek auf Webservern (Gunicorn mit Multiprozess-/Fork-Workern) und im Multithreading testen. Es werden auch einige Tests aus der Ultrajson-Bibliothek verwendet.
orjson ist die korrekteste der verglichenen Bibliotheken. Dieses Diagramm zeigt, wie jede Bibliothek insgesamt 342 JSON-Geräte aus den JSONTestSuite- und nativejson-benchmark-Tests verarbeitet:
Bibliothek | Ungültige JSON-Dokumente werden nicht abgelehnt | Gültige JSON-Dokumente nicht deserialisiert |
---|---|---|
orjson | 0 | 0 |
json | 17 | 0 |
Dies zeigt, dass alle Bibliotheken gültiges JSON deserialisieren, aber nur orjson die angegebenen ungültigen JSON-Fixtures korrekt ablehnt. Fehler entstehen größtenteils durch die Annahme ungültiger Zeichenfolgen und Zahlen.
Die obige Grafik kann mit dem pycorrectness
-Skript reproduziert werden.
Die Serialisierungs- und Deserialisierungsleistung von orjson ist durchweg besser als die von json
der Standardbibliothek. Die folgenden Grafiken veranschaulichen einige häufig verwendete Dokumente.
Bibliothek | Mittlere Latenz (Millisekunden) | Operationen pro Sekunde | Relativ (Latenz) |
---|---|---|---|
orjson | 0,1 | 8453 | 1 |
json | 1.3 | 765 | 11.1 |
Bibliothek | Mittlere Latenz (Millisekunden) | Operationen pro Sekunde | Relativ (Latenz) |
---|---|---|---|
orjson | 0,5 | 1889 | 1 |
json | 2.2 | 453 | 4.2 |
Bibliothek | Mittlere Latenz (Millisekunden) | Operationen pro Sekunde | Relativ (Latenz) |
---|---|---|---|
orjson | 0,01 | 103693 | 1 |
json | 0,13 | 7648 | 13.6 |
Bibliothek | Mittlere Latenz (Millisekunden) | Operationen pro Sekunde | Relativ (Latenz) |
---|---|---|---|
orjson | 0,04 | 23264 | 1 |
json | 0,1 | 10430 | 2.2 |
Bibliothek | Mittlere Latenz (Millisekunden) | Operationen pro Sekunde | Relativ (Latenz) |
---|---|---|---|
orjson | 0,3 | 3975 | 1 |
json | 3 | 338 | 11.8 |
Bibliothek | Mittlere Latenz (Millisekunden) | Operationen pro Sekunde | Relativ (Latenz) |
---|---|---|---|
orjson | 1.3 | 781 | 1 |
json | 4 | 250 | 3.1 |
Bibliothek | Mittlere Latenz (Millisekunden) | Operationen pro Sekunde | Relativ (Latenz) |
---|---|---|---|
orjson | 2.5 | 399 | 1 |
json | 29.8 | 33 | 11.9 |
Bibliothek | Mittlere Latenz (Millisekunden) | Operationen pro Sekunde | Relativ (Latenz) |
---|---|---|---|
orjson | 3 | 333 | 1 |
json | 18 | 55 | 6 |
Das Obige wurde mit Python 3.11.10 in einem Fedora 42-Container auf einer x86-64-v4-Maschine unter Verwendung des Artefakts orjson-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
auf PyPI gemessen. Die Latenzergebnisse können mit dem pybench
-Skript reproduziert werden.
Wahrscheinlich muss pip
auf Version 20.3 oder höher aktualisiert werden, um die neuesten Wheel-Formate Manylinux_x_y oder Universal2 zu unterstützen.
Dies geschieht, wenn es auf PyPI keine Binärräder (wie Manylinux) für Ihre Plattform gibt. Sie können Rust über rustup
oder einen Paketmanager installieren und dann wird es kompiliert.
Nein. Hierzu ist ein Schema erforderlich, das angibt, welche Typen erwartet werden und wie mit Fehlern usw. umgegangen wird. Dies wird von Datenvalidierungsbibliotheken auf einer Ebene darüber behandelt.
str
serialisiert? „Nein bytes
ist der richtige Typ für ein serialisiertes Blob.
Nein. orjsonl könnte angemessen sein.
Nein, es unterstützt RFC 8259.
Zum Verpacken von orjson sind mindestens Rust 1.72 und das Maturin-Build-Tool erforderlich. Der empfohlene Build-Befehl lautet:
maturin build --release --strip
Es profitiert davon, dass auch eine C-Build-Umgebung vorhanden ist, um ein schnelleres Deserialisierungs-Backend zu kompilieren. Ein Beispiel für die Verwendung von Clang und LTO finden Sie in den manylinux_2_28
-Builds dieses Projekts.
Die projekteigenen CI-Tests gegen nightly-2024-11-22
und Stable 1.72. Es ist ratsam, die nächtliche Version anzupinnen, da dieser Kanal wichtige Änderungen mit sich bringen kann. Die nächtliche Verwendung bietet einen erheblichen Leistungsvorteil.
orjson wurde für amd64, aarch64 und i686 unter Linux getestet und führt Cross-Compiles für arm7, ppc64le und s390x durch. Es wird entweder für aarch64 oder amd64 unter macOS getestet und je nach Version für das andere kompiliert. Für Windows wurde es auf amd64 und i686 getestet.
Außer libc gibt es keine Laufzeitabhängigkeiten.
Die Quelldistribution auf PyPI enthält die Quelle aller Abhängigkeiten und kann ohne Netzwerkzugriff erstellt werden. Die Datei kann von https://files.pythonhosted.org/packages/source/o/orjson/orjson-${version}.tar.gz
heruntergeladen werden.
Die Tests von orjson sind in der Quelldistribution auf PyPI enthalten. Die Anforderungen zum Ausführen der Tests sind in test/requirements.txt
angegeben. Die Tests sollten als Teil des Builds ausgeführt werden. Es kann mit pytest -q test
ausgeführt werden.
orjson wurde von ijl