orjson هي مكتبة JSON سريعة وصحيحة لبيثون. إنها تعتبر أسرع مكتبة Python لـ JSON وهي أكثر صحة من مكتبة json القياسية أو مكتبات الطرف الثالث الأخرى. يقوم بإجراء تسلسل لمثيلات فئة البيانات والوقت والرقم وUUID محليًا.
orjson.dumps() هو شيء يشبه 10x بسرعة json
، ويجري تسلسلًا للأنواع الشائعة والأنواع الفرعية، ويحتوي على معلمة default
للمتصل لتحديد كيفية إجراء تسلسل للأنواع التعسفية، ويحتوي على عدد من العلامات التي تتحكم في الإخراج.
orjson.loads() هو شيء يشبه سرعة json
بمقدار 2x، وهو متوافق تمامًا مع UTF-8 وRFC 8259 ("تنسيق تبادل بيانات JavaScript Object Notation (JSON"").
القراءة من الملفات والكتابة إليها، وملفات JSON المفصولة بأسطر، وما إلى ذلك لا توفرها المكتبة.
يدعم orjson CPython 3.8، 3.9، 3.10، 3.11، 3.12، 3.13، و3.14.
تقوم بتوزيع عجلات amd64/x86_64، وi686/x86، وaarch64/armv8، وarm7، وPOWER/ppc64le، وs390x لنظام Linux، وعجلات amd64 وaarch64 لنظام التشغيل macOS، وعجلات amd64 وi686/x86 لنظام التشغيل Windows.
orjson لا ولن يدعم PyPy، أو تصميمات Python المضمنة لنظام Android/iOS، أو المترجمين الفرعيين PEP 554.
تتبع الإصدارات الإصدارات الدلالية ويعتبر إجراء تسلسل لنوع كائن جديد بدون علامة الاشتراك بمثابة تغيير جذري.
تم ترخيص orjson بموجب تراخيص Apache 2.0 وMIT. المستودع ومتعقب المشكلات هو github.com/ijl/orjson، ويمكن إرسال التصحيحات هناك. يوجد سجل التغيير متاح في المستودع.
لتثبيت عجلة من PyPI، قم بتثبيت حزمة orjson
.
في تنسيق requirements.in
أو requirements.txt
، حدد:
orjson >= 3.10,<4
بتنسيق pyproject.toml
، حدد:
orjson = " ^3.10 "
لبناء عجلة، انظر التغليف.
هذا مثال على التسلسل، مع تحديد الخيارات، وإلغاء التسلسل:
> >> 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 ]]}
يقوم الإصدار 3 من orjson بإجراء تسلسل لأنواع أكثر من الإصدار 2. يتم الآن إجراء تسلسل للفئات الفرعية من str
و int
و dict
و list
. هذا أسرع وأكثر تشابهًا مع المكتبة القياسية. يمكن تعطيله باستخدام orjson.OPT_PASSTHROUGH_SUBCLASS
. يتم الآن إجراء تسلسل لمثيلات dataclasses.dataclass
افتراضيًا ولا يمكن تخصيصها في وظيفة default
ما لم يتم تحديد option=orjson.OPT_PASSTHROUGH_DATACLASS
. يتم إجراء تسلسل لمثيلات uuid.UUID
بشكل افتراضي. بالنسبة لأي نوع يتم إجراء تسلسل له الآن، يمكن إزالة التطبيقات الموجودة في الوظيفة default
والخيارات التي تمكنها، ولكن ليس هناك حاجة لذلك. لم يكن هناك أي تغيير في إلغاء التسلسل.
للترحيل من المكتبة القياسية، الاختلاف الأكبر هو أن orjson.dumps
يُرجع bytes
بينما يُرجع json.dumps
str
.
يجب على المستخدمين الذين لديهم كائنات dict
تستخدم مفاتيح غير str
تحديد option=orjson.OPT_NON_STR_KEYS
.
يتم استبدال sort_keys
بـ option=orjson.OPT_SORT_KEYS
.
يتم استبدال indent
option=orjson.OPT_INDENT_2
ولا يتم دعم مستويات المسافة البادئة الأخرى.
من المحتمل أن يكون ensure_ascii
غير مناسب اليوم ولا يمكن الهروب من أحرف UTF-8 إلى ASCII.
def dumps (
__obj : Any ,
default : Optional [ Callable [[ Any ], Any ]] = ...,
option : Optional [ int ] = ...,
) -> bytes : ...
dumps()
بتسلسل كائنات Python إلى JSON.
يقوم أصلاً بإجراء تسلسل str
و dict
و list
و tuple
و int
و float
و bool
و None
و dataclasses.dataclass
و typing.TypedDict
و datetime.datetime
و datetime.date
و datetime.time
و uuid.UUID
و numpy.ndarray
و orjson.Fragment
حالات orjson.Fragment
. وهو يدعم الأنواع التعسفية بشكل default
. يقوم بإجراء تسلسل للفئات الفرعية str
و int
و dict
و list
و dataclasses.dataclass
و enum.Enum
. لا يقوم بإجراء تسلسل للفئات الفرعية من tuple
لتجنب إجراء تسلسل لكائنات namedtuple
كمصفوفات. لتجنب إجراء تسلسل للفئات الفرعية، حدد الخيار orjson.OPT_PASSTHROUGH_SUBCLASS
.
الإخراج هو كائن bytes
يحتوي على UTF-8.
يتم تعليق قفل المترجم العالمي (GIL) طوال مدة المكالمة.
إنه يثير JSONEncodeError
على نوع غير مدعوم. تصف رسالة الاستثناء هذه الكائن غير الصالح مع رسالة الخطأ Type is not JSON serializable: ...
. لإصلاح هذه المشكلة، حدد الافتراضي.
يؤدي ذلك إلى ظهور JSONEncodeError
على str
تحتوي على UTF-8 غير صالح.
يؤدي ذلك إلى ظهور JSONEncodeError
على عدد صحيح يتجاوز 64 بت افتراضيًا، أو 53 بت باستخدام OPT_STRICT_INTEGER
.
يُثير JSONEncodeError
إذا كان dict
يحتوي على مفتاح من نوع آخر غير str
، ما لم يتم تحديد OPT_NON_STR_KEYS
.
فإنه يثير JSONEncodeError
إذا كان الإخراج default
يتكرر للمعالجة بشكل default
أكثر من 254 مستوى عميقًا.
فإنه يثير JSONEncodeError
على المراجع الدائرية.
فإنه يثير JSONEncodeError
إذا كان tzinfo
على كائن التاريخ والوقت غير مدعوم.
JSONEncodeError
هي فئة فرعية من TypeError
. هذا من أجل التوافق مع المكتبة القياسية.
إذا كان الفشل ناتجًا عن استثناء default
، فسيقوم JSONEncodeError
بتسلسل الاستثناء الأصلي كـ __cause__
.
لإجراء تسلسل لفئة فرعية أو أنواع عشوائية، حدد default
باعتباره قابلاً للاستدعاء والذي يُرجع نوعًا مدعومًا. قد يكون default
دالة، أو لامدا، أو مثيل فئة قابل للاستدعاء. لتحديد عدم معالجة النوع بشكل default
، قم برفع استثناء مثل 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
قد يُرجع الكائن القابل default
كائنًا يجب معالجته بشكل default
حتى 254 مرة قبل ظهور الاستثناء.
من المهم أن يثير default
استثناءً إذا تعذر التعامل مع النوع. بخلاف ذلك، تُرجع بايثون ضمنيًا None
، والذي يظهر للمتصل كقيمة مشروعة ويتم تسلسله:
> >> 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}'
لتعديل كيفية تسلسل البيانات، حدد option
. كل option
هو عدد صحيح ثابت في orjson
. لتحديد خيارات متعددة، قم بإخفائها معًا، على سبيل المثال، option=orjson.OPT_STRICT_INTEGER | orjson.OPT_NAIVE_UTC
.
إلحاق n
بالإخراج. يعد هذا وسيلة ملائمة وتحسينًا لنمط dumps(...) + "n"
. كائنات bytes
غير قابلة للتغيير وهذا النمط ينسخ المحتويات الأصلية.
> >> import orjson
> >> orjson . dumps ([])
b"[]"
> >> orjson . dumps ([], option = orjson . OPT_APPEND_NEWLINE )
b"[] n "
إخراج طباعة جميلة مع مسافة بادئة من مسافتين. وهذا يعادل indent=2
في المكتبة القياسية. الطباعة الجميلة أبطأ والإخراج أكبر. orjson هي أسرع مكتبة مقارنة في الطباعة الجميلة ولديها تباطؤ أقل بكثير في الطباعة الجميلة مقارنة بالمكتبة القياسية. هذا الخيار متوافق مع جميع الخيارات الأخرى.
> >> 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 }'
إذا تم عرضها، تظهر المسافة البادئة وفواصل الأسطر كما يلي:
{
"a" : " b " ,
"c" : {
"d" : true
},
"e" : [
1 ,
2
]
}
يقيس هذا إجراء تسلسل لتركيبة github.json على أنها مضغوطة (52 كيلو بايت) أو جميلة (64 كيلو بايت):
مكتبة | المدمجة (مللي ثانية) | جميلة (مللي ثانية) | مقابل أورجسون |
---|---|---|---|
com.orjson | 0.01 | 0.02 | 1 |
json | 0.13 | 0.54 | 34 |
يقيس هذا إجراء تسلسل لتركيبة citm_catalog.json، وهو أسوأ الحالات نظرًا لكمية التداخل والأسطر الجديدة، على شكل مضغوط (489 كيلو بايت) أو جميل (1.1 ميجا بايت):
مكتبة | المدمجة (مللي ثانية) | جميلة (مللي ثانية) | مقابل أورجسون |
---|---|---|---|
com.orjson | 0.25 | 0.45 | 1 |
json | 3.01 | 24.42 | 54.4 |
يمكن إعادة إنتاج هذا باستخدام البرنامج النصي pyindent
.
إجراء تسلسل لكائنات datetime.datetime
بدون tzinfo
كـ UTC. ليس لهذا أي تأثير على كائنات datetime.datetime
التي تم ضبط tzinfo
عليها.
> >> 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
من نوع آخر غير str
. يتيح ذلك أن تكون مفاتيح dict
واحدة من str
و int
و float
و bool
و None
و datetime.datetime
و datetime.date
و datetime.time
و enum.Enum
و uuid.UUID
. للمقارنة، تقوم المكتبة القياسية بإجراء تسلسل str
أو int
أو float
أو bool
أو None
افتراضيًا. تعتبر معايير orjson أسرع في إجراء تسلسل للمفاتيح غير str
من المكتبات الأخرى. هذا الخيار أبطأ بالنسبة لمفاتيح str
من الخيار الافتراضي.
> >> 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]}'
يتم إجراء تسلسل لهذه الأنواع عمومًا بالطريقة التي ستكون بها كقيم، على سبيل المثال، لا يزال datetime.datetime
عبارة عن سلسلة RFC 3339 ويحترم الخيارات التي تؤثر عليه. الاستثناء هو أن التسلسل int
لا يحترم OPT_STRICT_INTEGER
.
ينطوي هذا الخيار على خطر إنشاء مفاتيح مكررة. وذلك لأن الكائنات غير str
قد يتم إجراء تسلسل لها إلى نفس str
كمفتاح موجود، على سبيل المثال، {"1": true, 1: false}
. سيتم إجراء تسلسل للمفتاح الأخير الذي سيتم إدراجه في dict
، ومن المفترض أن يأخذ برنامج إلغاء تسلسل JSON آخر تواجد للمفتاح (في ما سبق، false
). سيتم فقدان القيمة الأولى.
هذا الخيار متوافق مع orjson.OPT_SORT_KEYS
. إذا تم استخدام الفرز، لاحظ أن الفرز غير مستقر ولن يكون من الممكن التنبؤ به بالنسبة للمفاتيح المكررة.
> >> 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}'
يقيس هذا تسلسل 589 كيلو بايت من JSON يشتمل على list
مكونة من 100 dict
، حيث يحتوي كل dict
على 365 مفتاحًا من مفاتيح int
مرتبة عشوائيًا تمثل طوابع زمنية للعصر بالإضافة إلى مفتاح str
واحد وقيمة كل مفتاح عبارة عن عدد صحيح واحد. في "مفاتيح str"، تم تحويل المفاتيح إلى str
قبل التسلسل، ولا يزال orjson يحدد option=orjson.OPT_NON_STR_KEYS
(والذي يكون دائمًا أبطأ إلى حد ما).
مكتبة | مفاتيح str (مللي ثانية) | مفاتيح كثافة العمليات (مللي ثانية) | مفاتيح int مرتبة (مللي ثانية) |
---|---|---|---|
com.orjson | 0.5 | 0.93 | 2.08 |
json | 2.72 | 3.59 |
json فارغ لأنه يؤدي إلى ظهور خطأ TypeError
عند محاولة الفرز قبل تحويل كافة المفاتيح إلى str
. يمكن إعادة إنتاج ذلك باستخدام البرنامج النصي pynonstr
.
لا تقم بإجراء تسلسل لحقل microsecond
في مثيلات datetime.datetime
و 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"'
تمرير مثيلات dataclasses.dataclass
إلى default
. يسمح هذا بتخصيص مخرجاتهم ولكنه أبطأ بكثير.
> >> 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"}'
المرور عبر مثيلات datetime.datetime
و datetime.date
و datetime.time
إلى default
. يتيح ذلك إجراء تسلسل لأوقات التاريخ بتنسيق مخصص، على سبيل المثال، تواريخ 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"}'
لا يؤثر هذا على أوقات التاريخ في مفاتيح dict
في حالة استخدام OPT_NON_STR_KEYS.
الفئات الفرعية للعبور من الأنواع المضمنة إلى 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'"******"'
لا يؤثر هذا على تسلسل الفئات الفرعية كمفاتيح dict
في حالة استخدام OPT_NON_STR_KEYS.
تم إهمال هذا وليس له أي تأثير في الإصدار 3. في الإصدار 2، كان هذا مطلوبًا لإجراء تسلسل لمثيلات dataclasses.dataclass
. للمزيد، راجع فئة البيانات.
إجراء تسلسل لمثيلات numpy.ndarray
. للمزيد، انظر نومي.
تم إهمال هذا وليس له أي تأثير في الإصدار 3. في الإصدار 2، كان هذا مطلوبًا لإجراء تسلسل لمثيلات uuid.UUID
. للمزيد، راجع UUID.
تسلسل مفاتيح dict
بترتيب فرزها. الافتراضي هو إجراء تسلسل بترتيب غير محدد. وهذا يعادل sort_keys=True
في المكتبة القياسية.
يمكن استخدام هذا للتأكد من أن الترتيب محدد للتجزئة أو الاختبارات. لديها عقوبة أداء كبيرة ولا ينصح بها بشكل عام.
> >> 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}'
يقيس هذا إجراء تسلسل لتركيبات twitter.json دون فرزها وفرزها:
مكتبة | غير مصنف (مللي ثانية) | مرتبة (مللي ثانية) | مقابل أورجسون |
---|---|---|---|
com.orjson | 0.11 | 0.3 | 1 |
json | 1.36 | 1.93 | 6.4 |
يمكن إعادة إنتاج المعيار باستخدام البرنامج النصي pysort
.
الفرز ليس ترتيبًا/معرفة بالإعدادات المحلية:
> >> import orjson
> >> orjson . dumps ({ "a" : 1 , "ä" : 2 , "A" : 3 }, option = orjson . OPT_SORT_KEYS )
b'{"A":3,"a":1," xc3 xa4 ":2}'
هذا هو نفس سلوك الفرز مثل المكتبة القياسية.
يتم أيضًا إجراء تسلسل dataclass
كخرائط ولكن هذا ليس له أي تأثير عليها.
فرض حد 53 بت على الأعداد الصحيحة. والحد الأقصى هو 64 بت، وهو نفس مكتبة بايثون القياسية. للمزيد، راجع int.
قم بإجراء تسلسل للمنطقة الزمنية UTC على مثيلات datetime.datetime
كـ Z
بدلاً من +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
JSON الذي تم تسلسله بالفعل في المستند. هذه طريقة فعالة لتضمين كائنات JSON الثنائية الكبيرة من ذاكرة التخزين المؤقت، أو حقل JSONB، أو كائن متسلسل بشكل منفصل دون إلغاء تسلسل كائنات Python أولاً عبر loads()
.
> >> import orjson
> >> orjson . dumps ({ "key" : "zxc" , "data" : orjson . Fragment ( b'{"a": "b", "c": 1}' )})
b'{"key":"zxc","data":{"a": "b", "c": 1}}'
لا يقوم بإعادة التنسيق: لن يؤثر orjson.OPT_INDENT_2
على كائن ثنائي كبير الحجم مضغوط ولن تتم إعادة كتابة كائن JSON ثنائي كبير الحجم مطبوع بشكل جميل على أنه مضغوط.
يجب أن يكون الإدخال bytes
أو str
ويتم تقديمه كوسيطة موضعية.
يؤدي هذا إلى ظهور orjson.JSONEncodeError
إذا تم تقديم str
وكان الإدخال غير صالح UTF-8. وإلا فلن يتم التحقق من الصحة ومن الممكن كتابة JSON غير صالح. هذا لا يهرب من الشخصيات. يتم اختبار التنفيذ حتى لا يتعطل إذا تم تقديم سلاسل غير صالحة أو JSON غير صالح.
def loads ( __obj : Union [ bytes , bytearray , memoryview , str ]) -> Any : ...
يقوم loads()
بإلغاء تسلسل JSON إلى كائنات Python. يتم إلغاء التسلسل إلى كائنات dict
و list
و int
و float
و str
و bool
و None
.
يتم قبول الإدخال bytes
و bytearray
و memoryview
و str
. إذا كان الإدخال موجودًا ككائن memoryview
أو bytearray
أو bytes
، فمن المستحسن تمرير هذه العناصر مباشرة بدلاً من إنشاء كائن str
غير ضروري. أي orjson.loads(b"{}")
بدلاً من orjson.loads(b"{}".decode("utf-8"))
. وهذا له استخدام أقل للذاكرة وزمن وصول أقل.
يجب أن يكون الإدخال صالحًا لـ UTF-8.
يحتفظ orjson بذاكرة تخزين مؤقت لمفاتيح الخريطة طوال مدة العملية. يؤدي هذا إلى انخفاض صافي في استخدام الذاكرة عن طريق تجنب السلاسل المكررة. يجب أن تكون المفاتيح بحد أقصى 64 بايت ليتم تخزينها مؤقتًا ويتم تخزين 2048 إدخالاً.
يتم تعليق قفل المترجم العالمي (GIL) طوال مدة المكالمة.
فإنه يثير JSONDecodeError
إذا تم إعطاء نوع غير صالح أو JSON غير صالح. يتضمن ذلك ما إذا كان الإدخال يحتوي على NaN
أو Infinity
أو -Infinity
، وهو ما تسمح به المكتبة القياسية، ولكنه ليس JSON صالحًا.
فإنه يثير JSONDecodeError
إذا كانت مجموعة من المصفوفة أو الكائن تتكرر بعمق 1024 مستوى.
JSONDecodeError
هي فئة فرعية من json.JSONDecodeError
و ValueError
. هذا من أجل التوافق مع المكتبة القياسية.
يقوم orjson بإجراء تسلسل لمثيلات dataclasses.dataclass
أصلاً. يقوم بإجراء تسلسل للمثيلات بمعدل 40 إلى 50 مرة بنفس سرعة المكتبات الأخرى ويتجنب التباطؤ الشديد الذي يحدث في المكتبات الأخرى مقارنة بتسلسل dict
.
إنه مدعوم لتمرير جميع متغيرات فئات البيانات، بما في ذلك فئات البيانات التي تستخدم __slots__
، وفئات البيانات المجمدة، وتلك ذات السمات الاختيارية أو الافتراضية، والفئات الفرعية. هناك فائدة أداء لعدم استخدام __slots__
.
مكتبة | إملاء (مللي ثانية) | فئة البيانات (ملي ثانية) | مقابل أورجسون |
---|---|---|---|
com.orjson | 0.43 | 0.95 | 1 |
json | 5.81 | 38.32 | 40 |
يقيس هذا إجراء تسلسل لـ 555 كيلو بايت من JSON وorjson محليًا والمكتبات الأخرى باستخدام default
لإجراء تسلسل لمخرجات dataclasses.asdict()
. يمكن إعادة إنتاج ذلك باستخدام البرنامج النصي pydataclass
.
يتم إجراء تسلسل لفئات البيانات كخرائط، مع تسلسل كل سمة وبالترتيب الوارد في تعريف الفئة:
> >> 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 بإجراء تسلسل لكائنات datetime.datetime
إلى تنسيق RFC 3339، على سبيل المثال، "1970-01-01T00:00:00+00:00". هذه مجموعة فرعية من ISO 8601 وهي متوافقة مع isoformat()
في المكتبة القياسية.
> >> 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
المثيلات ذات tzinfo
التي None
، أو datetime.timezone.utc
، أو مثيل المنطقة الزمنية من وحدة python3.9+ zoneinfo
، أو مثيل المنطقة الزمنية من مكتبات pendulum
، أو pytz
، أو dateutil
/ arrow
التابعة لجهة خارجية.
من الأسرع استخدام zoneinfo.ZoneInfo
الخاص بالمكتبة القياسية للمناطق الزمنية.
يجب ألا تحتوي كائنات datetime.time
على tzinfo
.
> >> import orjson , datetime
> >> orjson . dumps ( datetime . time ( 12 , 0 , 15 , 290 ))
b'"12:00:15.000290"'
سيتم دائمًا إجراء تسلسل لكائنات datetime.date
.
> >> import orjson , datetime
> >> orjson . dumps ( datetime . date ( 1900 , 1 , 2 ))
b'"1900-01-02"'
تؤدي الأخطاء في tzinfo
إلى ظهور JSONEncodeError
.
لتعطيل تسلسل كائنات datetime
، حدد الخيار orjson.OPT_PASSTHROUGH_DATETIME
.
لاستخدام اللاحقة "Z" بدلاً من "+00:00" للإشارة إلى وقت UTC ("Zulu")، استخدم الخيار orjson.OPT_UTC_Z
.
لافتراض أن أوقات التاريخ بدون المنطقة الزمنية هي UTC، استخدم الخيار orjson.OPT_NAIVE_UTC
.
يقوم orjson بإجراء تسلسل للتعدادات أصلاً. تنطبق الخيارات على قيمها.
> >> 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"'
يمكن إجراء تسلسل للتعدادات التي تحتوي على أعضاء من الأنواع غير المدعومة باستخدام 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 بتسلسل وإلغاء تسلسل العوامات ذات الدقة المزدوجة دون فقدان الدقة والتقريب المتسق.
يقوم orjson.dumps()
بإجراء تسلسل لـ Nan وInfinity و-Infinity، التي لا تتوافق مع JSON، باعتبارها 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 بإجراء تسلسل وإلغاء تسلسل الأعداد الصحيحة 64 بت بشكل افتراضي. النطاق المدعوم هو الحد الأدنى لعدد صحيح 64 بت موقّع (-9223372036854775807) إلى الحد الأقصى لعدد صحيح 64 بت غير موقّع (18446744073709551615). وهذا متوافق على نطاق واسع، ولكن هناك تطبيقات تدعم فقط 53 بت للأعداد الصحيحة، على سبيل المثال، متصفحات الويب. بالنسبة لهذه التطبيقات، يمكن تكوين dumps()
لرفع JSONEncodeError
على القيم التي تتجاوز نطاق 53 بت.
> >> 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 بتسلسل numpy.ndarray
و 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
و numpy.bool
.
orjson متوافق مع كل من numpy v1 وv2.
orjson أسرع من جميع المكتبات المقارنة في إجراء تسلسل لمثيلات numpy. يتطلب تسلسل البيانات الرقمية تحديد 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]]'
يجب أن يكون الصفيف عبارة عن صفيف C متجاور ( C_CONTIGUOUS
) وأحد أنواع البيانات المدعومة.
لاحظ الفرق بين إجراء تسلسل numpy.float32
باستخدام ndarray.tolist()
أو orjson.dumps(..., option=orjson.OPT_SERIALIZE_NUMPY)
: يتم تحويل tolist()
إلى double
قبل إجراء التسلسل بينما لا يتم تحويل المسار الأصلي لـ orjson. يمكن أن يؤدي هذا إلى تقريب مختلف.
يتم إجراء تسلسل لمثيلات numpy.datetime64
كسلاسل RFC 3339 وتؤثر عليها خيارات التاريخ والوقت.
> >> 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"'
إذا لم يكن المصفوفة مصفوفة C متجاورة، أو تحتوي على نوع بيانات غير مدعوم، أو تحتوي على numpy.datetime64
باستخدام تمثيل غير مدعوم (على سبيل المثال، بيكو ثانية)، فإن orjson يقع في default
. بشكل default
، يمكن تحديد obj.tolist()
.
إذا لم تكن المصفوفة في نطاق endianness الأصلي، على سبيل المثال، مصفوفة من قيم endian كبيرة على نظام endian صغير، فسيتم رفع orjson.JSONEncodeError
.
إذا كان المصفوفة مشوهة، فسيتم رفع orjson.JSONEncodeError
.
يقيس هذا إجراء تسلسل لـ 92 ميجابايت من JSON من numpy.ndarray
بأبعاد (50000, 100)
وقيم numpy.float64
:
مكتبة | الكمون (ملي ثانية) | فرق RSS (MiB) | مقابل أورجسون |
---|---|---|---|
com.orjson | 105 | 105 | 1 |
json | 1,481 | 295 | 14.2 |
يقيس هذا تسلسل 100 ميجابايت من JSON من numpy.ndarray
بأبعاد (100000, 100)
وقيم numpy.int32
:
مكتبة | الكمون (ملي ثانية) | فرق RSS (MiB) | مقابل أورجسون |
---|---|---|---|
com.orjson | 68 | 119 | 1 |
json | 684 | 501 | 10.1 |
يقيس هذا تسلسل 105 ميجابايت من JSON من numpy.ndarray
بأبعاد (100000, 200)
وقيم numpy.bool
:
مكتبة | الكمون (ملي ثانية) | فرق RSS (MiB) | مقابل أورجسون |
---|---|---|---|
com.orjson | 50 | 125 | 1 |
json | 573 | 398 | 11.5 |
في هذه المعايير، يقوم orjson بإجراء تسلسل محليًا ويقوم json
بإجراء تسلسل ndarray.tolist()
default
. يقيس عمود RSS ذروة استخدام الذاكرة أثناء التسلسل. يمكن استنساخ هذا باستخدام البرنامج النصي pynumpy
.
لا يعتمد orjson على التثبيت أو التجميع على numpy. التنفيذ مستقل، ويقرأ numpy.ndarray
باستخدام PyArrayInterface
.
Orjson صارم بشأن توافق UTF-8. هذا أكثر صرامة من وحدة json الخاصة بالمكتبة القياسية، والتي ستقوم بإجراء تسلسل وإلغاء تسلسل بدائل UTF-16، على سبيل المثال، "ud800"، التي تعتبر UTF-8 غير صالحة.
إذا تم إعطاء orjson.dumps()
str
لا تحتوي على UTF-8 صالح، فسيتم ظهور orjson.JSONEncodeError
. إذا استقبل loads()
UTF-8 غير صالح، فسيتم ظهور orjson.JSONDecodeError
.
> >> 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 '
لبذل أفضل جهد لإلغاء تسلسل المدخلات السيئة، قم أولاً بفك تشفير bytes
باستخدام وسيطة replace
أو lossy
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 بتسلسل مثيلات uuid.UUID
إلى تنسيق RFC 4122، على سبيل المثال، "f81d4fae-7dec-11d0-a765-00a0c91e6bf6".
> >> import orjson , uuid
> >> orjson . dumps ( uuid . uuid5 ( uuid . NAMESPACE_DNS , "python.org" ))
b'"886313e1-3b8a-5372-9b90-0c9aee199e5d"'
المكتبة لديها اختبارات شاملة. توجد اختبارات ضد التركيبات في مستودعات JSONTestSuite وnativejson-benchmark. تم اختباره حتى لا يصطدم بالقائمة الكبيرة للسلاسل المشاغب. تم اختباره لعدم تسرب الذاكرة. تم اختباره حتى لا يتعطل ولا يقبل UTF-8 غير الصالح. هناك اختبارات تكامل تمارس استخدام المكتبة في خوادم الويب (gunicorn باستخدام العمال متعددي العمليات/المتشعبين) وعندما تكون متعددة الخيوط. ويستخدم أيضًا بعض الاختبارات من مكتبة Ultrajson.
orjson هو الأصح بين المكتبات المقارنة. يوضح هذا الرسم البياني كيف تتعامل كل مكتبة مع 342 تركيبات JSON من اختبارات JSONTestSuite واختبارات originaljson-benchmark:
مكتبة | لم يتم رفض مستندات JSON غير الصالحة | لم يتم إلغاء تسلسل مستندات JSON الصالحة |
---|---|---|
com.orjson | 0 | 0 |
json | 17 | 0 |
يوضح هذا أن كافة المكتبات تقوم بإلغاء تسلسل JSON الصالح ولكن orjson فقط هو الذي يرفض بشكل صحيح تركيبات JSON غير الصالحة. ترجع الأخطاء إلى حد كبير إلى قبول سلاسل وأرقام غير صالحة.
يمكن إعادة إنتاج الرسم البياني أعلاه باستخدام البرنامج النصي pycorrectness
.
يعد أداء التسلسل وإلغاء التسلسل لـ orjson أفضل دائمًا من json
الخاص بالمكتبة القياسية. توضح الرسوم البيانية أدناه بعض المستندات شائعة الاستخدام.
مكتبة | الكمون المتوسط (ملي ثانية) | العمليات في الثانية الواحدة | نسبي (زمن الوصول) |
---|---|---|---|
com.orjson | 0.1 | 8453 | 1 |
json | 1.3 | 765 | 11.1 |
مكتبة | الكمون المتوسط (ملي ثانية) | العمليات في الثانية الواحدة | نسبي (زمن الوصول) |
---|---|---|---|
com.orjson | 0.5 | 1889 | 1 |
json | 2.2 | 453 | 4.2 |
مكتبة | الكمون المتوسط (ملي ثانية) | العمليات في الثانية الواحدة | نسبي (زمن الوصول) |
---|---|---|---|
com.orjson | 0.01 | 103693 | 1 |
json | 0.13 | 7648 | 13.6 |
مكتبة | الكمون المتوسط (ملي ثانية) | العمليات في الثانية الواحدة | نسبي (زمن الوصول) |
---|---|---|---|
com.orjson | 0.04 | 23264 | 1 |
json | 0.1 | 10430 | 2.2 |
مكتبة | الكمون المتوسط (ملي ثانية) | العمليات في الثانية الواحدة | نسبي (زمن الوصول) |
---|---|---|---|
com.orjson | 0.3 | 3975 | 1 |
json | 3 | 338 | 11.8 |
مكتبة | الكمون المتوسط (ملي ثانية) | العمليات في الثانية الواحدة | نسبي (زمن الوصول) |
---|---|---|---|
com.orjson | 1.3 | 781 | 1 |
json | 4 | 250 | 3.1 |
مكتبة | الكمون المتوسط (ملي ثانية) | العمليات في الثانية الواحدة | نسبي (زمن الوصول) |
---|---|---|---|
com.orjson | 2.5 | 399 | 1 |
json | 29.8 | 33 | 11.9 |
مكتبة | الكمون المتوسط (ملي ثانية) | العمليات في الثانية الواحدة | نسبي (زمن الوصول) |
---|---|---|---|
com.orjson | 3 | 333 | 1 |
json | 18 | 55 | 6 |
تم قياس ما سبق باستخدام Python 3.11.10 في حاوية Fedora 42 على جهاز x86-64-v4 باستخدام orjson-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
قطعة أثرية على PyPI. يمكن إعادة إنتاج نتائج الكمون باستخدام البرنامج النصي pybench
.
ربما تحتاج pip
إلى الترقية إلى الإصدار 20.3 أو إصدار أحدث لدعم أحدث تنسيقات عجلة linux_x_y أو Universal2.
يحدث هذا عندما لا تكون هناك عجلات ثنائية (مثل Manylinux) لمنصتك على PyPI. يمكنك تثبيت Rust من خلال rustup
أو مدير الحزم ومن ثم سيتم تجميعه.
لا، هذا يتطلب مخططًا يحدد الأنواع المتوقعة وكيفية التعامل مع الأخطاء وما إلى ذلك. تتم معالجة هذا من خلال مكتبات التحقق من صحة البيانات بمستوى أعلى من هذا.
str
؟ رقم bytes
هو النوع الصحيح للكائنات الثنائية الكبيرة المتسلسلة.
رقم orjsonl قد يكون مناسبا.
لا، فهو يدعم RFC 8259.
لحزم orjson يتطلب على الأقل Rust 1.72 وأداة البناء maturin. أمر البناء الموصى به هو:
maturin build --release --strip
إنه يستفيد أيضًا من وجود بيئة بناء C لتجميع واجهة خلفية أسرع لإلغاء التسلسل. راجع العديد من إصدارات manylinux_2_28
لهذا المشروع للحصول على مثال باستخدام clang وLTO.
اختبارات CI الخاصة بالمشروع مقابل nightly-2024-11-22
ومستقرة 1.72. ومن الحكمة تثبيت النسخة الليلية لأن هذه القناة يمكن أن تقدم تغييرات جذرية. هناك فائدة أداء كبيرة للاستخدام ليلاً.
تم اختبار orjson لـ amd64، وaarch64، وi686 على Linux، كما تم تجميعه بشكل متقاطع لـarm7، وppc64le، وs390x. يتم اختباره إما لـ aarch64 أو amd64 على نظام macOS ويتم تجميعه بشكل متقاطع للآخر، اعتمادًا على الإصدار. بالنسبة لنظام التشغيل Windows، تم اختباره على AMD64 وi686.
لا توجد تبعيات وقت التشغيل بخلاف libc.
يحتوي توزيع المصدر على PyPI على مصدر جميع التبعيات ويمكن إنشاؤه دون الوصول إلى الشبكة. يمكن تنزيل الملف من https://files.pythonhosted.org/packages/source/o/orjson/orjson-${version}.tar.gz
.
يتم تضمين اختبارات orjson في التوزيع المصدر على PyPI. تم تحديد متطلبات تشغيل الاختبارات في test/requirements.txt
. يجب تشغيل الاختبارات كجزء من البناء. يمكن تشغيله باستخدام pytest -q test
.
تمت كتابة orjson بواسطة ijl