orjson é uma biblioteca JSON rápida e correta para Python. Ele é considerado a biblioteca Python mais rápida para JSON e é mais correto do que a biblioteca JSON padrão ou outras bibliotecas de terceiros. Ele serializa instâncias de classe de dados, data e hora, numpy e UUID nativamente.
orjson.dumps() é cerca de 10x mais rápido que json
, serializa tipos e subtipos comuns, possui um parâmetro default
para o chamador especificar como serializar tipos arbitrários e possui vários sinalizadores que controlam a saída.
orjson.loads() é cerca de 2x mais rápido que json
e é estritamente compatível com UTF-8 e RFC 8259 ("O formato de intercâmbio de dados JavaScript Object Notation (JSON)").
Ler e gravar em arquivos, arquivos JSON delimitados por linha e assim por diante não são fornecidos pela biblioteca.
orjson suporta CPython 3.8, 3.9, 3.10, 3.11, 3.12, 3.13 e 3.14.
Ele distribui rodas amd64/x86_64, i686/x86, aarch64/armv8, arm7, POWER/ppc64le e s390x para Linux, rodas amd64 e aarch64 para macOS e rodas amd64 e i686/x86 para Windows.
orjson não oferece e não oferecerá suporte a PyPy, compilações Python incorporadas para Android/iOS ou subinterpretadores PEP 554.
As versões seguem o versionamento semântico e a serialização de um novo tipo de objeto sem um sinalizador de aceitação é considerada uma alteração significativa.
orjson é licenciado sob as licenças Apache 2.0 e MIT. O repositório e o rastreador de problemas são github.com/ijl/orjson, e patches podem ser enviados lá. Existe um CHANGELOG disponível no repositório.
Para instalar uma roda do PyPI, instale o pacote orjson
.
No formato requirements.in
ou requirements.txt
, especifique:
orjson >= 3.10,<4
No formato pyproject.toml
, especifique:
orjson = " ^3.10 "
Para construir uma roda, veja embalagem.
Este é um exemplo de serialização, com opções especificadas, e desserialização:
> >> 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 versão 3 serializa mais tipos que a versão 2. Subclasses de str
, int
, dict
e list
agora são serializadas. Isso é mais rápido e semelhante à biblioteca padrão. Pode ser desabilitado com orjson.OPT_PASSTHROUGH_SUBCLASS
. As instâncias dataclasses.dataclass
agora são serializadas por padrão e não podem ser customizadas em uma função default
, a menos que option=orjson.OPT_PASSTHROUGH_DATACLASS
seja especificado. As instâncias uuid.UUID
são serializadas por padrão. Para qualquer tipo que agora seja serializado, as implementações em uma função default
e as opções que as habilitam podem ser removidas, mas não precisam ser. Não houve alteração na desserialização.
Para migrar da biblioteca padrão, a maior diferença é que orjson.dumps
retorna bytes
e json.dumps
retorna a str
.
Usuários com objetos dict
usando chaves não str
devem especificar option=orjson.OPT_NON_STR_KEYS
.
sort_keys
é substituído por option=orjson.OPT_SORT_KEYS
.
indent
é substituído por option=orjson.OPT_INDENT_2
e outros níveis de recuo não são suportados.
ensure_ascii
provavelmente não é relevante hoje e os caracteres UTF-8 não podem ser escapados para ASCII.
def dumps (
__obj : Any ,
default : Optional [ Callable [[ Any ], Any ]] = ...,
option : Optional [ int ] = ...,
) -> bytes : ...
dumps()
serializa objetos Python para JSON.
Ele serializa nativamente str
, dict
, list
, tuple
, int
, float
, bool
, None
, dataclasses.dataclass
, typing.TypedDict
, datetime.datetime
, datetime.date
, datetime.time
, uuid.UUID
, numpy.ndarray
e orjson.Fragment
Instâncias orjson.Fragment
. Ele suporta tipos arbitrários por default
. Ele serializa subclasses de str
, int
, dict
, list
, dataclasses.dataclass
e enum.Enum
. Ele não serializa subclasses de tuple
para evitar a serialização de objetos namedtuple
como matrizes. Para evitar a serialização de subclasses, especifique a opção orjson.OPT_PASSTHROUGH_SUBCLASS
.
A saída é um objeto bytes
contendo UTF-8.
O bloqueio global do intérprete (GIL) é mantido durante a chamada.
Ele gera JSONEncodeError
em um tipo não suportado. Esta mensagem de exceção descreve o objeto inválido com a mensagem de erro Type is not JSON serializable: ...
. Para corrigir isso, especifique default.
Ele gera JSONEncodeError
em uma str
que contém UTF-8 inválido.
Ele gera JSONEncodeError
em um número inteiro que excede 64 bits por padrão ou, com OPT_STRICT_INTEGER
, 53 bits.
Ele gera JSONEncodeError
se um dict
tiver uma chave de tipo diferente de str
, a menos que OPT_NON_STR_KEYS
seja especificado.
Ele gera JSONEncodeError
se a saída do default
recorrer ao tratamento por default
com mais de 254 níveis de profundidade.
Ele gera JSONEncodeError
em referências circulares.
Ele gera JSONEncodeError
se um tzinfo
em um objeto datetime não for compatível.
JSONEncodeError
é uma subclasse de TypeError
. Isto é para compatibilidade com a biblioteca padrão.
Se a falha foi causada por uma exceção default
, JSONEncodeError
encadeia a exceção original como __cause__
.
Para serializar uma subclasse ou tipos arbitrários, especifique default
como um callable que retorna um tipo compatível. default
pode ser uma função, lambda ou instância de classe que pode ser chamada. Para especificar que um tipo não foi tratado por default
, gere uma exceção como 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
O callable default
pode retornar um objeto que deve ser tratado por default
até 254 vezes antes que uma exceção seja gerada.
É importante que default
gere uma exceção se um tipo não puder ser tratado. Caso contrário, Python retorna implicitamente None
, que aparece para o chamador como um valor legítimo e é serializado:
> >> 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}'
Para modificar como os dados são serializados, especifique option
. Cada option
é uma constante inteira em orjson
. Para especificar diversas opções, mascare-as juntas, por exemplo, option=orjson.OPT_STRICT_INTEGER | orjson.OPT_NAIVE_UTC
.
Anexe n
à saída. Esta é uma conveniência e otimização para o padrão de dumps(...) + "n"
. objetos bytes
são imutáveis e esse padrão copia o conteúdo original.
> >> import orjson
> >> orjson . dumps ([])
b"[]"
> >> orjson . dumps ([], option = orjson . OPT_APPEND_NEWLINE )
b"[] n "
Saída de impressão bonita com recuo de dois espaços. Isso é equivalente a indent=2
na biblioteca padrão. A impressão bonita é mais lenta e a saída maior. orjson é a biblioteca comparada mais rápida em impressão bonita e tem muito menos lentidão para impressão bonita do que a biblioteca padrão. Esta opção é compatível com todas as outras opções.
> >> 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 }'
Se exibido, o recuo e as quebras de linha aparecerão assim:
{
"a" : " b " ,
"c" : {
"d" : true
},
"e" : [
1 ,
2
]
}
Isso mede a serialização do fixture github.json como compacto (52KiB) ou bonito (64KiB):
Biblioteca | compacto (ms) | bonita (ms) | vs. |
---|---|---|---|
orjson | 0,01 | 0,02 | 1 |
JSON | 0,13 | 0,54 | 34 |
Isso mede a serialização do fixture citm_catalog.json, mais do pior caso devido à quantidade de aninhamento e novas linhas, como compacto (489KiB) ou bonito (1,1MiB):
Biblioteca | compacto (ms) | bonita (ms) | vs. |
---|---|---|---|
orjson | 0,25 | 0,45 | 1 |
JSON | 3.01 | 24h42 | 54,4 |
Isso pode ser reproduzido usando o script pyindent
.
Serialize objetos datetime.datetime
sem tzinfo
como UTC. Isso não tem efeito em objetos datetime.datetime
que possuem tzinfo
definido.
> >> 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"'
Serialize chaves dict
de tipo diferente de str
. Isso permite que as chaves dict
sejam str
, int
, float
, bool
, None
, datetime.datetime
, datetime.date
, datetime.time
, enum.Enum
e uuid.UUID
. Para efeito de comparação, a biblioteca padrão serializa str
, int
, float
, bool
ou None
por padrão. Os benchmarks orjson são mais rápidos na serialização de chaves não str
do que outras bibliotecas. Esta opção é mais lenta para chaves str
do que o padrão.
> >> 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]}'
Esses tipos geralmente são serializados como seriam como valores, por exemplo, datetime.datetime
ainda é uma string RFC 3339 e respeita as opções que a afetam. A exceção é que a serialização int
não respeita OPT_STRICT_INTEGER
.
Esta opção corre o risco de criar chaves duplicadas. Isso ocorre porque objetos não str
podem serializar para o mesmo str
que uma chave existente, por exemplo, {"1": true, 1: false}
. A última chave a ser inserida no dict
será serializada por último e um desserializador JSON provavelmente pegará a última ocorrência de uma chave (no exemplo acima, false
). O primeiro valor será perdido.
Esta opção é compatível com orjson.OPT_SORT_KEYS
. Se a classificação for usada, observe que a classificação é instável e imprevisível para chaves duplicadas.
> >> 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}'
Isso mede a serialização de 589 KiB de JSON, compreendendo uma list
de 100 dict
em que cada dict
tem 365 chaves int
classificadas aleatoriamente representando carimbos de data e hora de época, bem como uma chave str
e o valor de cada chave é um único número inteiro. Em "str keys", as chaves foram convertidas em str
antes da serialização, e orjson ainda especifica option=orjson.OPT_NON_STR_KEYS
(que é sempre um pouco mais lento).
Biblioteca | teclas str (ms) | chaves internas (ms) | chaves int classificadas (ms) |
---|---|---|---|
orjson | 0,5 | 0,93 | 2.08 |
JSON | 2,72 | 3,59 |
json está em branco porque gera TypeError
ao tentar classificar antes de converter todas as chaves em str
. Isso pode ser reproduzido usando o script pynonstr
.
Não serialize o campo microsecond
nas instâncias datetime.datetime
e 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"'
Passagem de instâncias dataclasses.dataclass
para default
. Isso permite personalizar sua saída, mas é muito mais lento.
> >> 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"}'
Transmita as instâncias datetime.datetime
, datetime.date
e datetime.time
para default
. Isso permite serializar datas e horas em um formato personalizado, por exemplo, datas 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"}'
Isso não afeta os horários nas chaves dict
se estiver usando OPT_NON_STR_KEYS.
Passagem de subclasses de tipos internos para 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'"******"'
Isso não afeta a serialização de subclasses como chaves dict
se estiver usando OPT_NON_STR_KEYS.
Isso está obsoleto e não tem efeito na versão 3. Na versão 2, isso era necessário para serializar instâncias dataclasses.dataclass
. Para mais informações, consulte classe de dados.
Serialize instâncias numpy.ndarray
. Para mais informações, consulte entorpecido.
Isso está obsoleto e não tem efeito na versão 3. Na versão 2, isso era necessário para serializar instâncias uuid.UUID
. Para obter mais informações, consulte UUID.
Serialize as chaves dict
em ordem de classificação. O padrão é serializar em uma ordem não especificada. Isso é equivalente a sort_keys=True
na biblioteca padrão.
Isso pode ser usado para garantir que o pedido seja determinístico para hash ou testes. Tem uma penalidade de desempenho substancial e não é recomendado em geral.
> >> 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}'
Isso mede a serialização do acessório twitter.json não classificado e classificado:
Biblioteca | não classificado (ms) | classificado (ms) | vs. |
---|---|---|---|
orjson | 0,11 | 0,3 | 1 |
JSON | 1,36 | 1,93 | 6.4 |
O benchmark pode ser reproduzido usando o script pysort
.
A classificação não reconhece agrupamento/localidade:
> >> import orjson
> >> orjson . dumps ({ "a" : 1 , "ä" : 2 , "A" : 3 }, option = orjson . OPT_SORT_KEYS )
b'{"A":3,"a":1," xc3 xa4 ":2}'
Este é o mesmo comportamento de classificação da biblioteca padrão.
dataclass
também serializa como mapas, mas isso não tem efeito sobre eles.
Aplicar limite de 53 bits em números inteiros. Caso contrário, o limite é de 64 bits, o mesmo da biblioteca padrão do Python. Para mais informações, consulte int.
Serialize um fuso horário UTC em instâncias datetime.datetime
como Z
em vez de +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
inclui JSON já serializado em um documento. Esta é uma maneira eficiente de incluir blobs JSON de um cache, campo JSONB ou objeto serializado separadamente sem primeiro desserializar para objetos Python por meio loads()
.
> >> import orjson
> >> orjson . dumps ({ "key" : "zxc" , "data" : orjson . Fragment ( b'{"a": "b", "c": 1}' )})
b'{"key":"zxc","data":{"a": "b", "c": 1}}'
Ele não reformata: orjson.OPT_INDENT_2
não afetará um blob compacto nem um blob JSON bem impresso será reescrito como compacto.
A entrada deve ser bytes
ou str
e fornecida como argumento posicional.
Isso gera orjson.JSONEncodeError
se um str
for fornecido e a entrada não for UTF-8 válida. Caso contrário, não faz validação e é possível escrever JSON inválido. Isso não escapa aos caracteres. A implementação é testada para não travar se forem fornecidas strings inválidas ou JSON inválido.
def loads ( __obj : Union [ bytes , bytearray , memoryview , str ]) -> Any : ...
loads()
desserializa JSON para objetos Python. Ele desserializa para dict
, list
, int
, float
, str
, bool
e None
objetos.
bytes
, bytearray
, memoryview
e str
input são aceitos. Se a entrada existir como um objeto memoryview
, bytearray
ou bytes
, é recomendável passá-los diretamente em vez de criar um objeto str
desnecessário. Ou seja, orjson.loads(b"{}")
em vez de orjson.loads(b"{}".decode("utf-8"))
. Isso tem menor uso de memória e menor latência.
A entrada deve ser UTF-8 válida.
orjson mantém um cache de chaves do mapa durante o processo. Isso causa uma redução líquida no uso de memória, evitando strings duplicadas. As chaves devem ter no máximo 64 bytes para serem armazenadas em cache e 2.048 entradas são armazenadas.
O bloqueio global do intérprete (GIL) é mantido durante a chamada.
Ele gera JSONDecodeError
se for fornecido um tipo inválido ou JSON inválido. Isso inclui se a entrada contém NaN
, Infinity
ou -Infinity
, o que a biblioteca padrão permite, mas não é JSON válido.
Ele gera JSONDecodeError
se uma combinação de array ou objeto recorrer a 1.024 níveis de profundidade.
JSONDecodeError
é uma subclasse de json.JSONDecodeError
e ValueError
. Isto é para compatibilidade com a biblioteca padrão.
orjson serializa instâncias de dataclasses.dataclass
nativamente. Ele serializa instâncias 40-50x mais rápido que outras bibliotecas e evita uma lentidão severa observada em outras bibliotecas em comparação com a serialização dict
.
É compatível para passar todas as variantes de classes de dados, incluindo classes de dados usando __slots__
, classes de dados congeladas, aquelas com atributos opcionais ou padrão e subclasses. Há um benefício de desempenho em não usar __slots__
.
Biblioteca | ditado (ms) | classe de dados (ms) | vs. |
---|---|---|---|
orjson | 0,43 | 0,95 | 1 |
JSON | 5,81 | 38,32 | 40 |
Isso mede a serialização de 555 KB de JSON, orjson nativamente e outras bibliotecas usando default
para serializar a saída de dataclasses.asdict()
. Isso pode ser reproduzido usando o script pydataclass
.
Dataclasses são serializadas como mapas, com cada atributo serializado e na ordem dada na definição da classe:
> >> 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 serializa objetos datetime.datetime
no formato RFC 3339, por exemplo, "1970-01-01T00:00:00+00:00". Este é um subconjunto da ISO 8601 e é compatível com isoformat()
na biblioteca padrão.
> >> 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
oferece suporte a instâncias com um tzinfo
que é None
, datetime.timezone.utc
, uma instância de fuso horário do módulo python3.9+ zoneinfo
ou uma instância de fuso horário das bibliotecas pendulum
, pytz
ou dateutil
/ arrow
de terceiros.
É mais rápido usar o zoneinfo.ZoneInfo
da biblioteca padrão para fusos horários.
Os objetos datetime.time
não devem ter um tzinfo
.
> >> import orjson , datetime
> >> orjson . dumps ( datetime . time ( 12 , 0 , 15 , 290 ))
b'"12:00:15.000290"'
Os objetos datetime.date
sempre serão serializados.
> >> import orjson , datetime
> >> orjson . dumps ( datetime . date ( 1900 , 1 , 2 ))
b'"1900-01-02"'
Erros com tzinfo
resultam no surgimento de JSONEncodeError
.
Para desabilitar a serialização de objetos datetime
, especifique a opção orjson.OPT_PASSTHROUGH_DATETIME
.
Para usar o sufixo "Z" em vez de "+00:00" para indicar o horário UTC ("Zulu"), use a opção orjson.OPT_UTC_Z
.
Para assumir que os horários sem fuso horário são UTC, use a opção orjson.OPT_NAIVE_UTC
.
orjson serializa enums nativamente. As opções se aplicam aos seus valores.
> >> 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"'
Enums com membros que não são tipos suportados podem ser serializados usando 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 serializa e desserializa flutuadores de precisão dupla sem perda de precisão e arredondamento consistente.
orjson.dumps()
serializa Nan, Infinity e -Infinity, que não são compatíveis com JSON, como 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 serializa e desserializa números inteiros de 64 bits por padrão. O intervalo suportado é o mínimo de um número inteiro assinado de 64 bits (-9223372036854775807) até o máximo de um número inteiro não assinado de 64 bits (18446744073709551615). Isto é amplamente compatível, mas existem implementações que suportam apenas 53 bits para números inteiros, por exemplo, navegadores web. Para essas implementações, dumps()
pode ser configurado para gerar um JSONEncodeError
em valores que excedam o intervalo de 53 bits.
> >> 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 serializa nativamente numpy.ndarray
e numpy.float64
individual, numpy.float32
, numpy.float16
( numpy.half
), numpy.int64
, numpy.int32
, numpy.int16
, numpy.int8
, numpy.uint64
, numpy.uint32
, numpy.uint16
, numpy.uint8
, instâncias numpy.uintp
, numpy.intp
, numpy.datetime64
e numpy.bool
.
orjson é compatível com numpy v1 e v2.
orjson é mais rápido do que todas as bibliotecas comparadas na serialização de instâncias numpy. A serialização de dados numpy requer a especificação de 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]]'
A matriz deve ser uma matriz C contígua ( C_CONTIGUOUS
) e um dos tipos de dados suportados.
Observe uma diferença entre serializar numpy.float32
usando ndarray.tolist()
ou orjson.dumps(..., option=orjson.OPT_SERIALIZE_NUMPY)
: tolist()
converte em double
antes da serialização e o caminho nativo de orjson não. Isso pode resultar em arredondamentos diferentes.
As instâncias numpy.datetime64
são serializadas como strings RFC 3339 e as opções de data e hora as afetam.
> >> 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"'
Se uma matriz não for uma matriz C contígua, contiver um tipo de dados não suportado ou contiver um numpy.datetime64
usando uma representação não suportada (por exemplo, picossegundos), orjson passará para default
. Em default
, obj.tolist()
pode ser especificado.
Se um array não estiver no endianness nativo, por exemplo, um array de valores big-endian em um sistema little-endian, orjson.JSONEncodeError
será gerado.
Se uma matriz estiver malformada, orjson.JSONEncodeError
será gerado.
Isso mede a serialização de 92 MiB de JSON de um numpy.ndarray
com dimensões de (50000, 100)
e valores numpy.float64
:
Biblioteca | Latência (ms) | Diferença RSS (MiB) | vs. |
---|---|---|---|
orjson | 105 | 105 | 1 |
JSON | 1.481 | 295 | 14.2 |
Isso mede a serialização de 100 MiB de JSON de um numpy.ndarray
com dimensões de (100000, 100)
e valores numpy.int32
:
Biblioteca | Latência (ms) | Diferença RSS (MiB) | vs. |
---|---|---|---|
orjson | 68 | 119 | 1 |
JSON | 684 | 501 | 10.1 |
Isso mede a serialização de 105 MiB de JSON de um numpy.ndarray
com dimensões de (100000, 200)
e valores numpy.bool
:
Biblioteca | Latência (ms) | Diferença RSS (MiB) | vs. |
---|---|---|---|
orjson | 50 | 125 | 1 |
JSON | 573 | 398 | 11,5 |
Nesses benchmarks, orjson serializa nativamente e json
serializa ndarray.tolist()
via default
. A coluna RSS mede o pico de uso de memória durante a serialização. Isso pode ser reproduzido usando o script pynumpy
.
orjson não tem dependência de instalação ou compilação do numpy. A implementação é independente, lendo numpy.ndarray
usando PyArrayInterface
.
orjson é rigoroso quanto à conformidade com UTF-8. Isso é mais rigoroso do que o módulo json da biblioteca padrão, que serializará e desserializará substitutos UTF-16, por exemplo, "ud800", que são UTF-8 inválidos.
Se orjson.dumps()
receber uma str
que não contém UTF-8 válido, orjson.JSONEncodeError
será gerado. Se loads()
receber UTF-8 inválido, orjson.JSONDecodeError
será gerado.
> >> 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 '
Para fazer o melhor esforço para desserializar entradas incorretas, primeiro decodifique bytes
usando o argumento replace
ou lossy
para 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 serializa instâncias uuid.UUID
para o formato RFC 4122, por exemplo, "f81d4fae-7dec-11d0-a765-00a0c91e6bf6".
> >> import orjson , uuid
> >> orjson . dumps ( uuid . uuid5 ( uuid . NAMESPACE_DNS , "python.org" ))
b'"886313e1-3b8a-5372-9b90-0c9aee199e5d"'
A biblioteca possui testes abrangentes. Existem testes em fixtures nos repositórios JSONTestSuite e nativejson-benchmark. Ele é testado para não colidir com a Grande Lista de Strings Impertinentes. Ele é testado para não vazar memória. Ele foi testado para não travar e não aceitar UTF-8 inválido. Existem testes de integração exercitando o uso da biblioteca em servidores web (gunicorn utilizando trabalhadores multiprocessos/forked) e quando multithreaded. Ele também usa alguns testes da biblioteca ultrajson.
orjson é a mais correta das bibliotecas comparadas. Este gráfico mostra como cada biblioteca lida com 342 acessórios JSON combinados dos testes JSONTestSuite e Nativejson-benchmark:
Biblioteca | Documentos JSON inválidos não rejeitados | Documentos JSON válidos não desserializados |
---|---|---|
orjson | 0 | 0 |
JSON | 17 | 0 |
Isso mostra que todas as bibliotecas desserializam JSON válido, mas apenas orjson rejeita corretamente os acessórios JSON inválidos fornecidos. Os erros são em grande parte devido à aceitação de strings e números inválidos.
O gráfico acima pode ser reproduzido usando o script pycorrectness
.
O desempenho de serialização e desserialização de orjson é consistentemente melhor que o json
da biblioteca padrão. Os gráficos abaixo ilustram alguns documentos comumente usados.
Biblioteca | Latência mediana (milissegundos) | Operações por segundo | Relativo (latência) |
---|---|---|---|
orjson | 0,1 | 8453 | 1 |
JSON | 1.3 | 765 | 11.1 |
Biblioteca | Latência mediana (milissegundos) | Operações por segundo | Relativo (latência) |
---|---|---|---|
orjson | 0,5 | 1889 | 1 |
JSON | 2.2 | 453 | 4.2 |
Biblioteca | Latência mediana (milissegundos) | Operações por segundo | Relativo (latência) |
---|---|---|---|
orjson | 0,01 | 103693 | 1 |
JSON | 0,13 | 7648 | 13.6 |
Biblioteca | Latência mediana (milissegundos) | Operações por segundo | Relativo (latência) |
---|---|---|---|
orjson | 0,04 | 23264 | 1 |
JSON | 0,1 | 10430 | 2.2 |
Biblioteca | Latência mediana (milissegundos) | Operações por segundo | Relativo (latência) |
---|---|---|---|
orjson | 0,3 | 3975 | 1 |
JSON | 3 | 338 | 11.8 |
Biblioteca | Latência mediana (milissegundos) | Operações por segundo | Relativo (latência) |
---|---|---|---|
orjson | 1.3 | 781 | 1 |
JSON | 4 | 250 | 3.1 |
Biblioteca | Latência mediana (milissegundos) | Operações por segundo | Relativo (latência) |
---|---|---|---|
orjson | 2,5 | 399 | 1 |
JSON | 29,8 | 33 | 11.9 |
Biblioteca | Latência mediana (milissegundos) | Operações por segundo | Relativo (latência) |
---|---|---|---|
orjson | 3 | 333 | 1 |
JSON | 18 | 55 | 6 |
O acima foi medido usando Python 3.11.10 em um contêiner Fedora 42 em uma máquina x86-64-v4 usando o artefato orjson-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
no PyPI. Os resultados de latência podem ser reproduzidos usando o script pybench
.
Provavelmente pip
precisa ser atualizado para a versão 20.3 ou posterior para suportar os formatos de roda manylinux_x_y ou universal2 mais recentes.
Isso acontece quando não há rodas binárias (como o Manylinux) para sua plataforma no PyPI. Você pode instalar o Rust através rustup
ou de um gerenciador de pacotes e então ele será compilado.
Não. Isso requer um esquema especificando quais tipos são esperados e como lidar com erros, etc. Isso é resolvido por bibliotecas de validação de dados um nível acima deste.
str
? Nº bytes
é o tipo correto para um blob serializado.
Não. orjsonl pode ser apropriado.
Não, ele suporta RFC 8259.
Para empacotar o orjson é necessário pelo menos Rust 1.72 e a ferramenta de compilação maturin. O comando de compilação recomendado é:
maturin build --release --strip
Ele também se beneficia de ter um ambiente de construção C para compilar um back-end de desserialização mais rápido. Veja as compilações manylinux_2_28
deste projeto para obter um exemplo usando clang e LTO.
Os próprios testes de CI do projeto contra nightly-2024-11-22
e stable 1.72. É prudente fixar a versão noturna porque esse canal pode introduzir alterações significativas. Há um benefício significativo de desempenho no uso noturno.
orjson é testado para amd64, aarch64 e i686 no Linux e faz compilação cruzada para arm7, ppc64le e s390x. Ele é testado para aarch64 ou amd64 no macOS e faz compilação cruzada para o outro, dependendo da versão. Para Windows é testado em AMD64 e i686.
Não há dependências de tempo de execução além da libc.
A distribuição de código-fonte no PyPI contém o código-fonte de todas as dependências e pode ser construída sem acesso à rede. O arquivo pode ser baixado em https://files.pythonhosted.org/packages/source/o/orjson/orjson-${version}.tar.gz
.
os testes do orjson estão incluídos na distribuição fonte no PyPI. Os requisitos para executar os testes são especificados em test/requirements.txt
. Os testes devem ser executados como parte da construção. Pode ser executado com pytest -q test
.
orjson foi escrito por ijl