orjson adalah perpustakaan JSON yang cepat dan benar untuk Python. Ini menjadi tolok ukur sebagai pustaka Python tercepat untuk JSON dan lebih tepat daripada pustaka json standar atau pustaka pihak ketiga lainnya. Ini membuat serial instance dataclass, datetime, numpy, dan UUID secara asli.
orjson.dumps() adalah sesuatu yang 10x lebih cepat dari json
, membuat serial tipe dan subtipe umum, memiliki parameter default
bagi pemanggil untuk menentukan cara membuat serial tipe arbitrer, dan memiliki sejumlah flag yang mengontrol output.
orjson.loads() kira-kira 2x lebih cepat dari json
, dan sangat sesuai dengan UTF-8 dan RFC 8259 ("Format Pertukaran Data JavaScript Object Notation (JSON)").
Membaca dari dan menulis ke file, file JSON yang dibatasi baris, dan sebagainya tidak disediakan oleh perpustakaan.
orjson mendukung CPython 3.8, 3.9, 3.10, 3.11, 3.12, 3.13, dan 3.14.
Ini mendistribusikan roda amd64/x86_64, i686/x86, aarch64/armv8, arm7, POWER/ppc64le, dan s390x untuk Linux, roda amd64 dan aarch64 untuk macOS, dan roda amd64 dan i686/x86 untuk Windows.
orjson tidak dan tidak akan mendukung PyPy, build Python tertanam untuk Android/iOS, atau subinterpreter PEP 554.
Rilis yang mengikuti pembuatan versi semantik dan membuat serial tipe objek baru tanpa tanda keikutsertaan dianggap sebagai perubahan yang dapat menyebabkan gangguan.
orjson dilisensikan di bawah lisensi Apache 2.0 dan MIT. Repositori dan pelacak masalah adalah github.com/ijl/orjson, dan patch dapat dikirimkan ke sana. Ada CHANGELOG yang tersedia di repositori.
Untuk memasang roda dari PyPI, instal paket orjson
.
Dalam format requirements.in
atau requirements.txt
, tentukan:
orjson >= 3.10,<4
Dalam format pyproject.toml
, tentukan:
orjson = " ^3.10 "
Untuk membuat roda, lihat kemasannya.
Ini adalah contoh serialisasi, dengan opsi yang ditentukan, dan deserialisasi:
> >> 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 versi 3 membuat serial lebih banyak tipe daripada versi 2. Subkelas str
, int
, dict
, dan list
sekarang diserialkan. Ini lebih cepat dan lebih mirip dengan perpustakaan standar. Itu dapat dinonaktifkan dengan orjson.OPT_PASSTHROUGH_SUBCLASS
. dataclasses.dataclass
instance sekarang diserialisasikan secara default dan tidak dapat dikustomisasi dalam fungsi default
kecuali option=orjson.OPT_PASSTHROUGH_DATACLASS
ditentukan. Instans uuid.UUID
diserialisasikan secara default. Untuk tipe apa pun yang sekarang berseri, implementasi dalam fungsi default
dan opsi yang mengaktifkannya dapat dihapus tetapi tidak perlu dihapus. Tidak ada perubahan dalam deserialisasi.
Untuk bermigrasi dari perpustakaan standar, perbedaan terbesarnya adalah orjson.dumps
mengembalikan bytes
dan json.dumps
mengembalikan str
.
Pengguna dengan objek dict
yang menggunakan kunci non- str
harus menentukan option=orjson.OPT_NON_STR_KEYS
.
sort_keys
digantikan oleh option=orjson.OPT_SORT_KEYS
.
indent
diganti dengan option=orjson.OPT_INDENT_2
dan level indentasi lainnya tidak didukung.
ensure_ascii
mungkin tidak relevan saat ini dan karakter UTF-8 tidak dapat di-escape ke ASCII.
def dumps (
__obj : Any ,
default : Optional [ Callable [[ Any ], Any ]] = ...,
option : Optional [ int ] = ...,
) -> bytes : ...
dumps()
membuat serial objek Python ke JSON.
Ini secara asli membuat serial str
, dict
, list
, tuple
, int
, float
, bool
, None
, dataclasses.dataclass
, typing.TypedDict
, datetime.datetime
, datetime.date
, datetime.time
, uuid.UUID
, numpy.ndarray
, dan orjson.Fragment
Contoh orjson.Fragment
. Ini mendukung tipe arbitrer melalui default
. Ini membuat serial subkelas str
, int
, dict
, list
, dataclasses.dataclass
, dan enum.Enum
. Itu tidak membuat serialisasi subkelas tuple
untuk menghindari serialisasi objek namedtuple
sebagai array. Untuk menghindari serialisasi subkelas, tentukan opsi orjson.OPT_PASSTHROUGH_SUBCLASS
.
Outputnya adalah objek bytes
yang berisi UTF-8.
Kunci juru bahasa global (GIL) ditahan selama panggilan berlangsung.
Ini memunculkan JSONEncodeError
pada tipe yang tidak didukung. Pesan pengecualian ini menjelaskan objek yang tidak valid dengan pesan kesalahan Type is not JSON serializable: ...
. Untuk memperbaikinya, tentukan default.
Ini memunculkan JSONEncodeError
pada str
yang berisi UTF-8 yang tidak valid.
Ini memunculkan JSONEncodeError
pada bilangan bulat yang melebihi 64 bit secara default atau, dengan OPT_STRICT_INTEGER
, 53 bit.
Ini memunculkan JSONEncodeError
jika dict
memiliki tipe kunci selain str
, kecuali OPT_NON_STR_KEYS
ditentukan.
Ini memunculkan JSONEncodeError
jika output default
berulang ke penanganan secara default
dengan kedalaman lebih dari 254 level.
Ini memunculkan JSONEncodeError
pada referensi melingkar.
Ini memunculkan JSONEncodeError
jika tzinfo
pada objek datetime tidak didukung.
JSONEncodeError
adalah subkelas dari TypeError
. Ini untuk kompatibilitas dengan perpustakaan standar.
Jika kegagalan disebabkan oleh pengecualian secara default
, maka JSONEncodeError
merangkai pengecualian asli sebagai __cause__
.
Untuk membuat serial subkelas atau tipe arbitrer, tentukan default
sebagai callable yang mengembalikan tipe yang didukung. default
mungkin berupa fungsi, lambda, atau instance kelas yang dapat dipanggil. Untuk menentukan bahwa suatu tipe tidak ditangani secara default
, berikan pengecualian seperti TypeError
.
> >> 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
Callable default
dapat mengembalikan objek yang harus ditangani secara default
hingga 254 kali sebelum pengecualian dimunculkan.
Penting agar default
memunculkan pengecualian jika suatu tipe tidak dapat ditangani. Python sebaliknya secara implisit mengembalikan None
, yang tampak bagi pemanggil seperti nilai yang sah dan diserialkan:
> >> 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}'
Untuk mengubah cara data diserialkan, tentukan option
. Setiap option
adalah konstanta bilangan bulat di orjson
. Untuk menentukan beberapa opsi, sembunyikan semuanya, misalnya, option=orjson.OPT_STRICT_INTEGER | orjson.OPT_NAIVE_UTC
.
Tambahkan n
ke output. Ini adalah kenyamanan dan optimasi untuk pola dumps(...) + "n"
. objek bytes
tidak dapat diubah dan pola ini menyalin konten aslinya.
> >> import orjson
> >> orjson . dumps ([])
b"[]"
> >> orjson . dumps ([], option = orjson . OPT_APPEND_NEWLINE )
b"[] n "
Hasil cetak cantik dengan indentasi dua spasi. Ini setara dengan indent=2
di perpustakaan standar. Pencetakan cantik lebih lambat dan output lebih besar. orjson adalah perpustakaan tercepat dibandingkan dalam pencetakan cantik dan memiliki lebih sedikit perlambatan dalam pencetakan cantik dibandingkan perpustakaan standar. Opsi ini kompatibel dengan semua opsi lainnya.
> >> 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 }'
Jika ditampilkan maka akan muncul indentasi dan linebreak seperti ini:
{
"a" : " b " ,
"c" : {
"d" : true
},
"e" : [
1 ,
2
]
}
Ini mengukur serialisasi perlengkapan github.json sebagai kompak (52KiB) atau cantik (64KiB):
Perpustakaan | kompak (ms) | cantik (ms) | vs.orjson |
---|---|---|---|
orjson | 0,01 | 0,02 | 1 |
json | 0,13 | 0,54 | 34 |
Tindakan ini membuat serialisasi perlengkapan citm_catalog.json, lebih merupakan kasus terburuk karena jumlah sarang dan baris baru, sebagai kompak (489KiB) atau cantik (1,1MiB):
Perpustakaan | kompak (ms) | cantik (ms) | vs.orjson |
---|---|---|---|
orjson | 0,25 | 0,45 | 1 |
json | 3.01 | 24.42 | 54.4 |
Ini dapat direproduksi menggunakan skrip pyindent
.
Buat serial objek datetime.datetime
tanpa tzinfo
sebagai UTC. Ini tidak berpengaruh pada objek datetime.datetime
yang memiliki tzinfo
yang disetel.
> >> 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"'
Buat serial kunci dict
dengan tipe selain str
. Hal ini memungkinkan kunci dict
menjadi salah satu dari str
, int
, float
, bool
, None
, datetime.datetime
, datetime.date
, datetime.time
, enum.Enum
, dan uuid.UUID
. Sebagai perbandingan, pustaka standar membuat serial str
, int
, float
, bool
atau None
secara default. tolok ukur orjson lebih cepat dalam membuat serial kunci non- str
dibandingkan perpustakaan lain. Opsi ini lebih lambat untuk kunci str
dibandingkan default.
> >> 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]}'
Tipe ini umumnya diserialkan sebagai nilai, misalnya, datetime.datetime
masih berupa string RFC 3339 dan menghormati opsi yang memengaruhinya. Pengecualiannya adalah serialisasi int
tidak menghormati OPT_STRICT_INTEGER
.
Opsi ini berisiko membuat kunci duplikat. Hal ini karena objek non- str
mungkin bersambung ke str
yang sama dengan kunci yang ada, misalnya, {"1": true, 1: false}
. Kunci terakhir yang dimasukkan ke dict
akan diserialkan terakhir dan deserializer JSON mungkin akan mengambil kemunculan kunci terakhir (di atas, false
). Nilai pertama akan hilang.
Opsi ini kompatibel dengan orjson.OPT_SORT_KEYS
. Jika pengurutan digunakan, perhatikan bahwa pengurutan tidak stabil dan tidak dapat diprediksi untuk kunci duplikat.
> >> 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}'
Ini mengukur serialisasi 589KiB JSON yang terdiri dari list
100 dict
yang setiap dict
memiliki 365 kunci int
yang diurutkan secara acak yang mewakili stempel waktu zaman serta satu kunci str
dan nilai untuk setiap kunci adalah bilangan bulat tunggal. Dalam "kunci str", kunci diubah menjadi str
sebelum serialisasi, dan orjson masih menentukan option=orjson.OPT_NON_STR_KEYS
(yang selalu agak lebih lambat).
Perpustakaan | tombol str (ms) | kunci int (ms) | kunci int diurutkan (ms) |
---|---|---|---|
orjson | 0,5 | 0,93 | 2.08 |
json | 2.72 | 3.59 |
json kosong karena memunculkan TypeError
saat mencoba mengurutkan sebelum mengonversi semua kunci menjadi str
. Ini dapat direproduksi menggunakan skrip pynonstr
.
Jangan membuat serial bidang microsecond
pada instance datetime.datetime
dan datetime.time
.
> >> 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"'
Lewati instance dataclasses.dataclass
ke default
. Hal ini memungkinkan penyesuaian keluarannya tetapi jauh lebih lambat.
> >> 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"}'
Lewati instance datetime.datetime
, datetime.date
, dan datetime.time
ke default
. Hal ini memungkinkan serialisasi tanggal waktu ke format khusus, misalnya tanggal HTTP:
> >> 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"}'
Ini tidak mempengaruhi waktu tanggal di kunci dict
jika menggunakan OPT_NON_STR_KEYS.
Lewati subkelas tipe bawaan ke 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'"******"'
Ini tidak mempengaruhi serialisasi subkelas sebagai kunci dict
jika menggunakan OPT_NON_STR_KEYS.
Ini sudah tidak digunakan lagi dan tidak berpengaruh pada versi 3. Dalam versi 2, hal ini diperlukan untuk membuat serial dataclasses.dataclass
instance. Untuk lebih lanjut, lihat kelas data.
Buat serial instance numpy.ndarray
. Untuk lebih lanjut, lihat numpy.
Ini sudah tidak digunakan lagi dan tidak berpengaruh pada versi 3. Dalam versi 2, hal ini diperlukan untuk membuat serialisasi instance uuid.UUID
. Selengkapnya lihat UUID.
Buat serial kunci dict
dalam urutan yang diurutkan. Standarnya adalah membuat serial dalam urutan yang tidak ditentukan. Ini setara dengan sort_keys=True
di perpustakaan standar.
Ini dapat digunakan untuk memastikan urutan bersifat deterministik untuk hashing atau pengujian. Ini memiliki penalti kinerja yang besar dan tidak direkomendasikan secara umum.
> >> 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}'
Tindakan ini membuat serialisasi perlengkapan twitter.json tidak disortir dan diurutkan:
Perpustakaan | tidak disortir (ms) | diurutkan (ms) | vs.orjson |
---|---|---|---|
orjson | 0,11 | 0,3 | 1 |
json | 1.36 | 1.93 | 6.4 |
Benchmark dapat direproduksi menggunakan skrip pysort
.
Penyortiran ini tidak sesuai dengan susunan/sadar lokal:
> >> import orjson
> >> orjson . dumps ({ "a" : 1 , "ä" : 2 , "A" : 3 }, option = orjson . OPT_SORT_KEYS )
b'{"A":3,"a":1," xc3 xa4 ":2}'
Ini adalah perilaku penyortiran yang sama seperti perpustakaan standar.
dataclass
juga bersambung sebagai peta tetapi ini tidak berpengaruh pada mereka.
Terapkan batas 53-bit pada bilangan bulat. Batasnya adalah 64 bit, sama dengan perpustakaan standar Python. Untuk lebih lanjut, lihat int.
Buat serial zona waktu UTC pada instance datetime.datetime
sebagai Z
bukan +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
menyertakan JSON yang sudah diserialkan dalam sebuah dokumen. Ini adalah cara yang efisien untuk memasukkan blob JSON dari cache, bidang JSONB, atau objek serial secara terpisah tanpa terlebih dahulu melakukan deserialisasi ke objek Python melalui loads()
.
> >> import orjson
> >> orjson . dumps ({ "key" : "zxc" , "data" : orjson . Fragment ( b'{"a": "b", "c": 1}' )})
b'{"key":"zxc","data":{"a": "b", "c": 1}}'
Tidak ada pemformatan ulang: orjson.OPT_INDENT_2
tidak akan memengaruhi gumpalan kompak dan gumpalan JSON yang dicetak cantik tidak akan ditulis ulang sebagai gumpalan kompak.
Inputnya harus berupa bytes
atau str
dan diberikan sebagai argumen posisi.
Ini memunculkan orjson.JSONEncodeError
jika str
diberikan dan input UTF-8 tidak valid. Jika tidak, ia tidak melakukan validasi dan ada kemungkinan untuk menulis JSON yang tidak valid. Hal ini tidak luput dari karakter. Implementasinya diuji agar tidak crash jika diberikan string yang tidak valid atau JSON yang tidak valid.
def loads ( __obj : Union [ bytes , bytearray , memoryview , str ]) -> Any : ...
loads()
melakukan deserialisasi JSON ke objek Python. Ini dideserialisasi menjadi objek dict
, list
, int
, float
, str
, bool
, dan None
.
bytes
, bytearray
, memoryview
, dan input str
diterima. Jika masukan ada sebagai objek memoryview
, bytearray
, atau bytes
, disarankan untuk meneruskannya secara langsung daripada membuat objek str
yang tidak perlu. Artinya, orjson.loads(b"{}")
bukan orjson.loads(b"{}".decode("utf-8"))
. Ini memiliki penggunaan memori yang lebih rendah dan latensi yang lebih rendah.
Masukannya harus UTF-8 yang valid.
orjson menyimpan cache kunci peta selama proses berlangsung. Hal ini menyebabkan pengurangan bersih dalam penggunaan memori dengan menghindari duplikat string. Kunci harus berukuran maksimal 64 byte untuk di-cache dan 2048 entri disimpan.
Kunci juru bahasa global (GIL) ditahan selama panggilan berlangsung.
Ini memunculkan JSONDecodeError
jika diberikan tipe yang tidak valid atau JSON yang tidak valid. Ini termasuk jika masukan berisi NaN
, Infinity
, atau -Infinity
, yang diizinkan oleh pustaka standar, namun bukan JSON yang valid.
Ini memunculkan JSONDecodeError
jika kombinasi array atau objek berulang sedalam 1024 level.
JSONDecodeError
adalah subkelas dari json.JSONDecodeError
dan ValueError
. Ini untuk kompatibilitas dengan perpustakaan standar.
orjson membuat serial instance dataclasses.dataclass
secara asli. Ini membuat serial instance 40-50x lebih cepat dari perpustakaan lain dan menghindari perlambatan parah yang terlihat di perpustakaan lain dibandingkan dengan membuat serial dict
.
Hal ini didukung untuk meneruskan semua varian kelas data, termasuk kelas data yang menggunakan __slots__
, kelas data yang dibekukan, kelas dengan atribut opsional atau default, dan subkelas. Ada manfaat kinerja jika tidak menggunakan __slots__
.
Perpustakaan | dikte (ms) | kelas data (ms) | vs.orjson |
---|---|---|---|
orjson | 0,43 | 0,95 | 1 |
json | 5.81 | 38.32 | 40 |
Ini mengukur pembuatan serial 555KiB JSON, orjson secara asli, dan pustaka lain menggunakan default
untuk membuat serial keluaran dataclasses.asdict()
. Ini dapat direproduksi menggunakan skrip pydataclass
.
Kelas data diserialkan sebagai peta, dengan setiap atribut diserialkan dan sesuai urutan yang diberikan pada definisi kelas:
> >> 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 membuat serial objek datetime.datetime
ke format RFC 3339, misalnya, "1970-01-01T00:00:00+00:00". Ini adalah bagian dari ISO 8601 dan kompatibel dengan isoformat()
di perpustakaan standar.
> >> 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
mendukung instance dengan tzinfo
yaitu None
, datetime.timezone.utc
, instance zona waktu dari modul python3.9+ zoneinfo
, atau instance zona waktu dari perpustakaan pendulum
, pytz
, atau dateutil
/ arrow
pihak ketiga.
Cara tercepat adalah menggunakan zoneinfo.ZoneInfo
perpustakaan standar untuk zona waktu.
objek datetime.time
tidak boleh memiliki tzinfo
.
> >> import orjson , datetime
> >> orjson . dumps ( datetime . time ( 12 , 0 , 15 , 290 ))
b'"12:00:15.000290"'
objek datetime.date
akan selalu bersambung.
> >> import orjson , datetime
> >> orjson . dumps ( datetime . date ( 1900 , 1 , 2 ))
b'"1900-01-02"'
Kesalahan dengan tzinfo
mengakibatkan JSONEncodeError
dimunculkan.
Untuk menonaktifkan serialisasi objek datetime
tentukan opsi orjson.OPT_PASSTHROUGH_DATETIME
.
Untuk menggunakan akhiran "Z" dan bukan "+00:00" untuk menunjukkan waktu UTC ("Zulu"), gunakan opsi orjson.OPT_UTC_Z
.
Untuk mengasumsikan waktu tanpa zona waktu adalah UTC, gunakan opsi orjson.OPT_NAIVE_UTC
.
orjson membuat serial enum secara asli. Pilihan berlaku untuk nilai-nilai mereka.
> >> 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"'
Enum dengan anggota yang bukan tipe yang didukung dapat diserialkan menggunakan default
:
> >> 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 membuat serialisasi dan deserialisasi pelampung presisi ganda tanpa kehilangan presisi dan pembulatan yang konsisten.
orjson.dumps()
membuat serialisasi Nan, Infinity, dan -Infinity, yang tidak sesuai dengan JSON, sebagai 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 membuat serialisasi dan deserialisasi bilangan bulat 64-bit secara default. Rentang yang didukung adalah bilangan bulat minimum 64-bit yang ditandatangani (-9223372036854775807) hingga bilangan bulat maksimum 64-bit yang tidak ditandatangani (18446744073709551615). Ini kompatibel secara luas, tetapi ada implementasi yang hanya mendukung 53-bit untuk bilangan bulat, misalnya browser web. Untuk implementasi tersebut, dumps()
dapat dikonfigurasi untuk menaikkan JSONEncodeError
pada nilai yang melebihi rentang 53-bit.
> >> 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 secara asli membuat serial numpy.ndarray
dan individu 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
, dan numpy.bool
contoh.
orjson kompatibel dengan numpy v1 dan v2.
orjson lebih cepat dari semua perpustakaan yang dibandingkan dalam membuat serialisasi instance numpy. Membuat serial data numpy memerlukan penentuan option=orjson.OPT_SERIALIZE_NUMPY
.
> >> 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]]'
Array harus berupa array C yang berdekatan ( C_CONTIGUOUS
) dan salah satu tipe data yang didukung.
Perhatikan perbedaan antara membuat serial numpy.float32
menggunakan ndarray.tolist()
atau orjson.dumps(..., option=orjson.OPT_SERIALIZE_NUMPY)
: tolist()
dikonversi menjadi double
sebelum membuat serial dan jalur asli orjson tidak. Hal ini dapat mengakibatkan pembulatan yang berbeda.
Instans numpy.datetime64
diserialkan sebagai string RFC 3339 dan opsi datetime memengaruhinya.
> >> 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"'
Jika array bukan array C yang bersebelahan, berisi tipe data yang tidak didukung, atau berisi numpy.datetime64
menggunakan representasi yang tidak didukung (misalnya, pikodetik), orjson akan masuk ke default
. Secara default
, obj.tolist()
dapat ditentukan.
Jika array tidak berada dalam endian asli, misalnya, array nilai big-endian pada sistem little-endian, orjson.JSONEncodeError
akan dimunculkan.
Jika array salah format, orjson.JSONEncodeError
dimunculkan.
Ini mengukur serialisasi 92MiB JSON dari numpy.ndarray
dengan dimensi nilai (50000, 100)
dan numpy.float64
:
Perpustakaan | Latensi (ms) | Perbedaan RSS (MiB) | vs.orjson |
---|---|---|---|
orjson | 105 | 105 | 1 |
json | 1.481 | 295 | 14.2 |
Ini mengukur serialisasi 100MiB JSON dari numpy.ndarray
dengan dimensi nilai (100000, 100)
dan numpy.int32
:
Perpustakaan | Latensi (ms) | Perbedaan RSS (MiB) | vs.orjson |
---|---|---|---|
orjson | 68 | 119 | 1 |
json | 684 | 501 | 10.1 |
Ini mengukur serialisasi 105MiB JSON dari numpy.ndarray
dengan dimensi (100000, 200)
dan nilai numpy.bool
:
Perpustakaan | Latensi (ms) | Perbedaan RSS (MiB) | vs.orjson |
---|---|---|---|
orjson | 50 | 125 | 1 |
json | 573 | 398 | 11.5 |
Dalam tolok ukur ini, orjson membuat serial secara native dan json
membuat serial ndarray.tolist()
melalui default
. Kolom RSS mengukur penggunaan memori puncak selama serialisasi. Ini dapat direproduksi menggunakan skrip pynumpy
.
orjson tidak memiliki ketergantungan instalasi atau kompilasi pada numpy. Implementasinya independen, membaca numpy.ndarray
menggunakan PyArrayInterface
.
orjson sangat ketat tentang kesesuaian UTF-8. Ini lebih ketat daripada modul json perpustakaan standar, yang akan membuat serialisasi dan deserialisasi pengganti UTF-16, misalnya, "ud800", yang merupakan UTF-8 tidak valid.
Jika orjson.dumps()
diberi str
yang tidak berisi UTF-8 yang valid, orjson.JSONEncodeError
akan dimunculkan. Jika loads()
menerima UTF-8 yang tidak valid, orjson.JSONDecodeError
akan dimunculkan.
> >> 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 '
Untuk melakukan upaya terbaik dalam melakukan deserialisasi masukan yang buruk, pertama-tama dekode bytes
menggunakan argumen replace
atau lossy
untuk 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 membuat serial instance uuid.UUID
ke format RFC 4122, misalnya, "f81d4fae-7dec-11d0-a765-00a0c91e6bf6".
> >> import orjson , uuid
> >> orjson . dumps ( uuid . uuid5 ( uuid . NAMESPACE_DNS , "python.org" ))
b'"886313e1-3b8a-5372-9b90-0c9aee199e5d"'
Perpustakaan memiliki tes yang komprehensif. Ada pengujian terhadap perlengkapan di repositori JSONTestSuite dan nativejson-benchmark. Ini diuji agar tidak menabrak Daftar Besar Senar Nakal. Ini diuji untuk tidak membocorkan memori. Ini diuji agar tidak mogok dan tidak menerima UTF-8 yang tidak valid. Ada tes integrasi yang menggunakan perpustakaan di server web (gunicorn menggunakan pekerja multiproses/bercabang) dan ketika multithread. Itu juga menggunakan beberapa tes dari perpustakaan ultrajson.
orjson adalah perpustakaan yang paling benar dibandingkan. Grafik ini menunjukkan bagaimana setiap perpustakaan menangani gabungan 342 perlengkapan JSON dari pengujian JSONTestSuite dan benchmark nativejson:
Perpustakaan | Dokumen JSON yang tidak valid tidak ditolak | Dokumen JSON yang valid tidak dideserialisasi |
---|---|---|
orjson | 0 | 0 |
json | 17 | 0 |
Hal ini menunjukkan bahwa semua perpustakaan melakukan deserialisasi JSON yang valid tetapi hanya orjson yang dengan benar menolak perlengkapan JSON yang tidak valid tersebut. Kesalahan sebagian besar disebabkan oleh penerimaan string dan angka yang tidak valid.
Grafik di atas dapat direproduksi menggunakan skrip pycorrectness
.
Kinerja serialisasi dan deserialisasi orjson secara konsisten lebih baik daripada json
perpustakaan standar. Grafik di bawah menggambarkan beberapa dokumen yang umum digunakan.
Perpustakaan | Latensi median (milidetik) | Operasi per detik | Relatif (latensi) |
---|---|---|---|
orjson | 0,1 | 8453 | 1 |
json | 1.3 | 765 | 11.1 |
Perpustakaan | Latensi median (milidetik) | Operasi per detik | Relatif (latensi) |
---|---|---|---|
orjson | 0,5 | 1889 | 1 |
json | 2.2 | 453 | 4.2 |
Perpustakaan | Latensi median (milidetik) | Operasi per detik | Relatif (latensi) |
---|---|---|---|
orjson | 0,01 | 103693 | 1 |
json | 0,13 | 7648 | 13.6 |
Perpustakaan | Latensi median (milidetik) | Operasi per detik | Relatif (latensi) |
---|---|---|---|
orjson | 0,04 | 23264 | 1 |
json | 0,1 | 10430 | 2.2 |
Perpustakaan | Latensi median (milidetik) | Operasi per detik | Relatif (latensi) |
---|---|---|---|
orjson | 0,3 | 3975 | 1 |
json | 3 | 338 | 11.8 |
Perpustakaan | Latensi median (milidetik) | Operasi per detik | Relatif (latensi) |
---|---|---|---|
orjson | 1.3 | 781 | 1 |
json | 4 | 250 | 3.1 |
Perpustakaan | Latensi median (milidetik) | Operasi per detik | Relatif (latensi) |
---|---|---|---|
orjson | 2.5 | 399 | 1 |
json | 29.8 | 33 | 11.9 |
Perpustakaan | Latensi median (milidetik) | Operasi per detik | Relatif (latensi) |
---|---|---|---|
orjson | 3 | 333 | 1 |
json | 18 | 55 | 6 |
Hal di atas diukur menggunakan Python 3.11.10 dalam wadah Fedora 42 pada mesin x86-64-v4 menggunakan artefak orjson-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
di PyPI. Hasil latensi dapat direproduksi menggunakan skrip pybench
.
Mungkin pip
perlu ditingkatkan ke versi 20.3 atau lebih baru untuk mendukung format roda manylinux_x_y atau universal2 terbaru.
Ini terjadi ketika tidak ada roda biner (seperti manylinux) untuk platform Anda di PyPI. Anda dapat menginstal Rust melalui rustup
atau manajer paket dan kemudian akan dikompilasi.
Tidak. Hal ini memerlukan skema yang menentukan jenis apa yang diharapkan dan cara menangani kesalahan, dll. Hal ini ditangani oleh pustaka validasi data satu tingkat di atasnya.
str
? Jumlah bytes
adalah tipe yang benar untuk blob berseri.
Tidak. orjsonl mungkin sesuai.
Tidak, ini mendukung RFC 8259.
Untuk mengemas orjson memerlukan setidaknya Rust 1.72 dan alat build maturin. Perintah build yang direkomendasikan adalah:
maturin build --release --strip
Ini mendapat manfaat dari juga memiliki lingkungan build C untuk mengkompilasi backend deserialisasi yang lebih cepat. Lihat build manylinux_2_28
proyek ini untuk contoh penggunaan clang dan LTO.
Pengujian CI proyek ini terhadap nightly-2024-11-22
dan stabil 1,72. Sebaiknya sematkan versi malam karena saluran tersebut dapat menyebabkan perubahan yang dapat menyebabkan gangguan. Ada manfaat kinerja yang signifikan dalam penggunaan nightly.
orjson diuji untuk amd64, aarch64, dan i686 di Linux dan kompilasi silang untuk arm7, ppc64le, dan s390x. Ini diuji untuk aarch64 atau amd64 di macOS dan kompilasi silang untuk yang lain, bergantung pada versi. Untuk Windows diuji pada amd64 dan i686.
Tidak ada dependensi runtime selain libc.
Distribusi sumber di PyPI berisi semua sumber dependensi dan dapat dibangun tanpa akses jaringan. File dapat diunduh dari https://files.pythonhosted.org/packages/source/o/orjson/orjson-${version}.tar.gz
.
tes orjson disertakan dalam distribusi sumber di PyPI. Persyaratan untuk menjalankan pengujian ditentukan dalam test/requirements.txt
. Pengujian harus dijalankan sebagai bagian dari build. Itu dapat dijalankan dengan pytest -q test
.
orjson ditulis oleh ijl