واحدة من أسرع مكتبات JSON في العالم. يقرأ Glaze ويكتب من ذاكرة الكائن، مما يبسط الواجهات ويقدم أداءً مذهلاً.
يدعم الصقيل أيضًا:
نقية، وتجميع انعكاس الوقت للهياكل
توافق JSON RFC 8259 مع التحقق من صحة UTF-8
دعم مكتبة C++ القياسية
رأس فقط
مباشرة إلى تسلسل الذاكرة/إلغاء التسلسل
قم بتجميع الخرائط الزمنية باستخدام عمليات البحث الثابتة عن الوقت والتجزئة المثالية
أغلفة قوية لتعديل سلوك القراءة/الكتابة (Wrappers)
استخدم وظائف القراءة/الكتابة المخصصة الخاصة بك (قراءة/كتابة مخصصة)
التعامل مع المفاتيح غير المعروفة بطريقة سريعة ومرنة
الوصول المباشر إلى الذاكرة من خلال بناء جملة مؤشر JSON
البيانات الثنائية من خلال نفس واجهة برمجة التطبيقات لتحقيق أقصى قدر من الأداء
لا توجد استثناءات (يتم تجميعها باستخدام -fno-exceptions
)
لا توجد معلومات ضرورية عن نوع وقت التشغيل (يتم تجميعها باستخدام -fno-rtti
)
معالجة الأخطاء السريعة مع ماس كهربائى
دعم JSON-RPC 2.0
إنشاء مخطط JSON
محمول للغاية، ويستخدم SWAR (SIMD داخل سجل) المحسن بعناية لتحقيق التوافق الواسع
دعم القراءة الجزئية والكتابة الجزئية
قراءة/كتابة ملف CSV
أكثر من ذلك بكثير!
راجع المستندات لمزيد من الوثائق.
مكتبة | وقت (توقيتات) الرحلة ذهابًا وإيابًا | الكتابة (ميجابايت/ثانية) | القراءة (ميجابايت/ثانية) |
---|---|---|---|
الصقيل | 1.04 | 1366 | 1224 |
سيمدجسون (حسب الطلب) | لا يوجد | لا يوجد | 1198 |
yyjson | 1.23 | 1005 | 1107 |
daw_json_link | 2.93 | 365 | 553 |
RapidJSON | 3.65 | 290 | 450 |
Boost.JSON (مباشر) | 4.76 | 199 | 447 |
json_struct | 5.50 | 182 | 326 |
نلوهمان | 15.71 | 84 | 80 |
رمز اختبار الأداء متاح هنا
تحذيرات الأداء: simdjson وyyjson رائعان، لكنهما يواجهان خسائر كبيرة في الأداء عندما لا تكون البيانات في التسلسل المتوقع أو عندما تكون أي مفاتيح مفقودة (تتفاقم المشكلة مع زيادة حجم الملف، حيث يجب إعادة التكرار من خلال المستند).
أيضًا، لا يدعم simdjson وyyjson معالجة السلسلة التلقائية التي تم تجاوزها، لذلك إذا كانت أي من السلاسل التي لم يتم تجاوزها حاليًا في هذا المعيار تحتوي على عملية هروب، فلن تتم معالجة عمليات الهروب.
يُظهر اختبار ABC مدى ضعف أداء simdjson عندما لا تكون المفاتيح بالتسلسل المتوقع:
مكتبة | القراءة (ميجابايت/ثانية) |
---|---|
الصقيل | 678 |
سيمدجسون (حسب الطلب) | 93 |
المواصفات الثنائية الموسومة: BEVE
متري | وقت (توقيتات) الرحلة ذهابًا وإيابًا | الكتابة (ميجابايت/ثانية) | القراءة (ميجابايت/ثانية) |
---|---|---|---|
الأداء الخام | 0.42 | 3235 | 2468 |
بيانات JSON المكافئة* | 0.42 | 3547 | 2706 |
حجم JSON: 670 بايت
حجم BEVE: 611 بايت
*حزم BEVE أكثر كفاءة من JSON، لذا فإن نقل نفس البيانات يكون أسرع.
سوف تنعكس البنية الخاصة بك تلقائيًا! لا توجد بيانات وصفية مطلوبة من قبل المستخدم.
struct my_struct
{
int i = 287 ;
double d = 3.14 ;
std::string hello = " Hello World " ;
std::array< uint64_t , 3 > arr = { 1 , 2 , 3 };
std::map<std::string, int > map{{ " one " , 1 }, { " two " , 2 }};
};
JSON (جميلة)
{
"i" : 287 ,
"d" : 3.14 ,
"hello" : " Hello World " ,
"arr" : [
1 ,
2 ,
3
],
"map" : {
"one" : 1 ,
"two" : 2
}
}
اكتب جسون
my_struct s{};
std::string buffer = glz::write_json(s).value_or( " error " );
أو
my_struct s{};
std::string buffer{};
auto ec = glz::write_json(s, buffer);
if (ec) {
// handle error
}
قراءة جسون
std::string buffer = R"( {"i":287,"d":3.14,"hello":"Hello World","arr":[1,2,3],"map":{"one":1,"two":2}} )" ;
auto s = glz::read_json<my_struct>(buffer);
if (s) // check std::expected
{
s. value (); // s.value() is a my_struct populated from buffer
}
أو
std::string buffer = R"( {"i":287,"d":3.14,"hello":"Hello World","arr":[1,2,3],"map":{"one":1,"two":2}} )" ;
my_struct s{};
auto ec = glz::read_json(s, buffer); // populates s from buffer
if (ec) {
// handle error
}
auto ec = glz::read_file_json(obj, " ./obj.json " , std::string{});
auto ec = glz::write_file_json(obj, " ./obj.json " , std::string{});
مهم
يجب أن يكون اسم الملف (الوسيطة الثانية) منتهيًا بقيمة خالية.
يتم إنشاء الإجراءات واختبارها باستخدام Clang (17+)، وMSVC (2022)، وGC (12+) على أنظمة Apple وWindows وLinux.
يسعى Glaze إلى الحفاظ على التوافق مع أحدث الإصدارات الثلاثة من دول مجلس التعاون الخليجي وClang، بالإضافة إلى أحدث إصدار من MSVC وApple Clang.
يتطلب Glaze معالجًا أوليًا متوافقًا مع معيار C++، والذي يتطلب علامة /Zc:preprocessor
عند الإنشاء باستخدام MSVC.
يحتوي CMake على خيار glaze_ENABLE_AVX2
. سيحاول هذا استخدام تعليمات AVX2
SIMD في بعض الحالات لتحسين الأداء، طالما أن النظام الذي تقوم بتكوينه يدعمه. اضبط هذا الخيار على OFF
لتعطيل مجموعة تعليمات AVX2، كما لو كنت تقوم بالتجميع المتقاطع لـ Arm. إذا كنت لا تستخدم CMake، فإن الماكرو GLZ_USE_AVX2
يقوم بتمكين الميزة إذا تم تحديدها.
include (FetchContent)
FetchContent_Declare(
glaze
GIT_REPOSITORY https://github.com/stephenberry/glaze.git
GIT_TAG main
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(glaze)
target_link_libraries ( ${PROJECT_NAME} PRIVATE glaze::glaze)
find_package(glaze REQUIRED)
target_link_libraries(main PRIVATE glaze::glaze)
import libs = libglaze%lib{glaze}
إذا كنت ترغب في تخصيص تفكيرك، فيمكنك اختياريًا كتابة الكود أدناه:
تعد بيانات التعريف هذه ضرورية أيضًا للبنيات غير المجمعة القابلة للتهيئة.
template <>
struct glz ::meta<my_struct> {
using T = my_struct;
static constexpr auto value = object(
&T::i,
&T::d,
&T::hello,
&T::arr,
&T::map
);
};
struct my_struct
{
int i = 287 ;
double d = 3.14 ;
std::string hello = " Hello World " ;
std::array< uint64_t , 3 > arr = { 1 , 2 , 3 };
std::map<std::string, int > map{{ " one " , 1 }, { " two " , 2 }};
struct glaze {
using T = my_struct;
static constexpr auto value = glz::object(
&T::i,
&T::d,
&T::hello,
&T::arr,
&T::map
);
};
};
عندما تقوم بتعريف بيانات تعريف Glaze، ستعكس الكائنات تلقائيًا الأسماء غير الثابتة لمؤشرات كائن العضو لديك. ومع ذلك، إذا كنت تريد أسماء مخصصة أو قمت بتسجيل وظائف lambda أو أغلفة لا توفر أسماء لحقولك، فيمكنك اختياريًا إضافة أسماء الحقول في بيانات التعريف الخاصة بك.
مثال على الأسماء المخصصة:
template <>
struct glz ::meta<my_struct> {
using T = my_struct;
static constexpr auto value = object(
" integer " , &T::i,
" double " , &T::d,
" string " , &T::hello,
" array " , &T::arr,
" my map " , &T::map
);
};
كل سلسلة من هذه السلاسل اختيارية ويمكن إزالتها للحقول الفردية إذا كنت تريد أن ينعكس الاسم.
الأسماء مطلوبة لـ:
- متغيرات الأعضاء constexpr ثابتة
- مغلفة
- وظائف لامدا
يوفر Glaze واجهة برمجة تطبيقات لانعكاس وقت الترجمة والتي يمكن تعديلها عبر تخصصات glz::meta
. تستخدم واجهة برمجة تطبيقات الانعكاس هذه انعكاسًا خالصًا ما لم يتم توفير تخصص glz::meta
، وفي هذه الحالة يتم تجاوز السلوك الافتراضي بواسطة المطور.
static_assert (glz::reflect<my_struct>::size == 5 ); // Number of fields
static_assert (glz::reflect<my_struct>::keys[ 0 ] == " i " ); // Access keys
تحذير
لقد تم إضفاء الطابع الرسمي على الحقول glz::reflect
الموضحة أعلاه ومن غير المرجح أن تتغير. قد تتطور الحقول الأخرى داخل بنية glz::reflect
مع استمرارنا في إضفاء الطابع الرسمي على المواصفات. لذلك، قد تحدث تغييرات جذرية للحقول غير الموثقة في المستقبل.
يمكن تحقيق القراءة والكتابة المخصصة من خلال نهج التخصص القوي from
/ to
، والذي تم وصفه هنا: custom-serialization.md. ومع ذلك، هذا يعمل فقط مع الأنواع التي يحددها المستخدم.
بالنسبة لحالات الاستخدام الشائع أو الحالات التي يجب أن يكون لمتغير عضو معين قراءة وكتابة خاصتين، يمكنك استخدام glz::custom
لتسجيل وظائف أعضاء القراءة/الكتابة، أو وظائف std::functions، أو وظائف lambda.
struct custom_encoding
{
uint64_t x{};
std::string y{};
std::array< uint32_t , 3 > z{};
void read_x ( const std::string& s) {
x = std::stoi (s);
}
uint64_t write_x () {
return x;
}
void read_y ( const std::string& s) {
y = " hello " + s;
}
auto & write_z () {
z[ 0 ] = 5 ;
return z;
}
};
template <>
struct glz ::meta<custom_encoding>
{
using T = custom_encoding;
static constexpr auto value = object( " x " , custom<&T::read_x, &T::write_x>, //
" y " , custom<&T::read_y, &T::y>, //
" z " , custom<&T::z, &T::write_z>);
};
suite custom_encoding_test = [] {
" custom_reading " _test = [] {
custom_encoding obj{};
std::string s = R"( {"x":"3","y":"world","z":[1,2,3]} )" ;
expect (! glz::read_json (obj, s));
expect (obj. x == 3 );
expect (obj. y == " helloworld " );
expect (obj. z == std::array< uint32_t , 3 >{ 1 , 2 , 3 });
};
" custom_writing " _test = [] {
custom_encoding obj{};
std::string s = R"( {"x":"3","y":"world","z":[1,2,3]} )" ;
expect (! glz::read_json (obj, s));
std::string out{};
expect ( not glz::write_json (obj, out));
expect (out == R"( {"x":3,"y":"helloworld","z":[5,2,3]} )" );
};
};
عند استخدام مؤشرات الأعضاء (على سبيل المثال &T::a
) يجب أن تتطابق بنيات فئة C++ مع واجهة JSON. قد يكون من المرغوب فيه تعيين فئات C++ ذات تخطيطات مختلفة لنفس واجهة الكائن. ويتم تحقيق ذلك من خلال تسجيل وظائف لامدا بدلاً من مؤشرات الأعضاء.
template <>
struct glz ::meta<Thing> {
static constexpr auto value = object(
" i " , []( auto && self) -> auto & { return self. subclass . i ; }
);
};
ستكون القيمة التي تم تمريرها self
إلى دالة lambda عبارة عن كائن Thing
، وتسمح لنا دالة lambda بجعل الفئة الفرعية غير مرئية لواجهة الكائن.
تعمل وظيفة Lambda بشكل افتراضي على إرجاع النسخ، لذلك عادةً ما يكون نوع الإرجاع auto&
مطلوبًا حتى تتم كتابة التزجيج على الذاكرة.
لاحظ أنه يمكن أيضًا تحقيق إعادة التعيين من خلال المؤشرات/المراجع، حيث يتعامل التزجيج مع القيم والمؤشرات والمراجع بنفس الطريقة عند الكتابة/القراءة.
يمكن التعامل مع الفئة كقيمة أساسية على النحو التالي:
struct S {
int x{};
};
template <>
struct glz ::meta<S> {
static constexpr auto value{ &S::x };
};
أو باستخدام لامدا:
template <>
struct glz ::meta<S> {
static constexpr auto value = []( auto & self) -> auto & { return self. x ; };
};
يعتبر Glaze آمنًا للاستخدام مع الرسائل غير الموثوقة. يتم إرجاع الأخطاء كرموز خطأ، عادةً داخل glz::expected
، والذي يتصرف تمامًا مثل std::expected
.
يعمل Glaze على معالجة أخطاء الدائرة القصيرة، مما يعني أن التحليل يخرج بسرعة كبيرة في حالة مواجهة خطأ.
لإنشاء المزيد من رسائل الخطأ المفيدة، اتصل بـ format_error
:
auto pe = glz::read_json(obj, buffer);
if (pe) {
std::string descriptive_error = glz::format_error (pe, buffer);
}
حالة الاختبار هذه:
{ "Hello" : " World " x, "color": "red" }
ينتج هذا الخطأ:
1:17: expected_comma
{"Hello":"World"x, "color": "red"}
^
للدلالة على أن x غير صالح هنا.
يوصى باستخدام سلسلة غير ثابتة std::string
لمخازن الإدخال المؤقتة، حيث يسمح ذلك لـ Glaze بتحسين الأداء باستخدام الحشو المؤقت وسيتم إنهاء المخزن المؤقت بقيمة null.
افتراضيًا، يتم تعيين الخيار null_terminated
على true
ويجب استخدام المخازن المؤقتة ذات القيمة الخالية عند تحليل JSON. يمكن إيقاف تشغيل الخيار مع خسارة بسيطة في الأداء، مما يسمح بمخازن مؤقتة منتهية غير خالية:
constexpr glz::opts options{. null_terminated = false };
auto ec = glz::read<options>(value, buffer); // read in a non-null terminated buffer
الإنهاء الصفري غير مطلوب عند تحليل BEVE (ثنائي). لا فرق في الأداء.
تحذير
حاليًا، null_terminated = false
غير صالح لتحليل ملف CSV ويجب أن تكون المخازن المؤقتة منتهية بقيمة null.
يتم تحويل أنواع المصفوفات بشكل منطقي إلى قيم مصفوفة JSON. تُستخدم المفاهيم للسماح بالحاويات المختلفة وحتى حاويات المستخدم إذا كانت تتوافق مع واجهات المكتبة القياسية.
glz::array
(تجميع الأنواع المختلطة للوقت)std::tuple
(أنواع مختلطة من وقت الترجمة)std::array
std::vector
std::deque
std::list
std::forward_list
std::span
std::set
std::unordered_set
يتم تحويل أنواع الكائنات بشكل منطقي إلى قيم كائنات JSON، مثل الخرائط. مثل JSON، يتعامل Glaze مع تعريفات الكائنات كخرائط غير مرتبة. لذلك ليس من الضروري أن يتطابق ترتيب تخطيط الكائن مع نفس التسلسل الثنائي في C++.
glz::object
(أنواع مختلطة من وقت الترجمة)std::map
std::unordered_map
std::pair
(يمكّن المفاتيح الديناميكية في تخزين المكدس)تتم معالجة
std::pair
ككائن بمفتاح وقيمة واحدة، ولكن عند استخدامstd::pair
في مصفوفة، يقوم Glaze بتسلسل الأزواج في كائن واحد. سيتم إجراء تسلسلstd::vector<std::pair<...>>
ككائن واحد. إذا كنت لا تريد هذا السلوك، فاضبط خيار وقت الترجمة.concatenate = false
.
std::variant
راجع معالجة المتغيرات لمزيد من المعلومات.
std::unique_ptr
std::shared_ptr
std::optional
يمكن تخصيص الأنواع الخالية عن طريق إدخال صالح أو إلغاؤها بواسطة الكلمة الأساسية null
.
std::unique_ptr< int > ptr{};
std::string buffer{};
expect ( not glz::write_json (ptr, buffer));
expect (buffer == " null " );
expect ( not glz::read_json (ptr, " 5 " ));
expect (*ptr == 5 );
buffer.clear();
expect ( not glz::write_json (ptr, buffer));
expect (buffer == " 5 " );
expect ( not glz::read_json (ptr, " null " ));
expect (! bool (ptr));
بشكل افتراضي، سيتم كتابة التعدادات وقراءتها في شكل عدد صحيح. لا يعد glz::meta
ضروريًا إذا كان هذا هو السلوك المطلوب.
ومع ذلك، إذا كنت تفضل استخدام التعدادات كسلاسل في JSON، فيمكن تسجيلها في glz::meta
كما يلي:
enum class Color { Red, Green, Blue };
template <>
struct glz ::meta<Color> {
using enum Color;
static constexpr auto value = enumerate(Red,
Green,
Blue
);
};
قيد الاستخدام:
Color color = Color::Red;
std::string buffer{};
glz::write_json (color, buffer);
expect (buffer == " " Red " " );
التعليقات مدعومة بالمواصفات المحددة هنا: JSONC
يتم توفير دعم قراءة التعليقات من خلال glz::read_jsonc
أو glz::read<glz::opts{.comments = true}>(...)
.
يمكن كتابة JSON المنسق مباشرة عبر خيار وقت الترجمة:
auto ec = glz::write<glz::opts{. prettify = true }>(obj, buffer);
أو يمكن تنسيق نص JSON باستخدام الدالة glz::prettify_json
:
std::string buffer = R"( {"i":287,"d":3.14,"hello":"Hello World","arr":[1,2,3]} )" );
auto beautiful = glz::prettify_json(buffer);
beautiful
الان :
{
"i" : 287 ,
"d" : 3.14 ,
"hello" : " Hello World " ,
"arr" : [
1 ,
2 ,
3
]
}
لكتابة JSON المصغر:
auto ec = glz::write_json(obj, buffer); // default is minified
لتقليل مكالمة نصية JSON:
std::string minified = glz::minify_json(buffer);
إذا كنت ترغب في طلب JSON مصغر أو تعلم أن مدخلاتك سيتم تصغيرها دائمًا، فيمكنك الحصول على المزيد من الأداء باستخدام خيار وقت الترجمة .minified = true
.
auto ec = glz::read<glz::opts{. minified = true }>(obj, buffer);
يدعم Glaze تسجيل مجموعة من الأعلام المنطقية التي تعمل كمصفوفة من خيارات السلسلة:
struct flags_t {
bool x{ true };
bool y{};
bool z{ true };
};
template <>
struct glz ::meta< flags_t > {
using T = flags_t ;
static constexpr auto value = flags( " x " , &T::x, " y " , &T::y, " z " , &T::z);
};
مثال:
flags_t s{};
expect (glz::write_json(s) == R"([ " x " , " z " ])");
تمت كتابة "x"
و "z"
فقط، لأنهما صحيحتان. ستؤدي القراءة في المخزن المؤقت إلى تعيين القيم المنطقية المناسبة.
عند كتابة BEVE، تستخدم
flags
بتًا واحدًا فقط لكل منطقي (محاذاة البايت).
في بعض الأحيان تريد فقط كتابة هياكل JSON بسرعة قدر الإمكان. يوفر Glaze هياكل تشبه الصفوف تسمح لك بتكديس الهياكل المخصصة لكتابة JSON بسرعة عالية. تتم تسمية هذه الهياكل باسم glz::obj
للكائنات و glz::arr
للمصفوفات.
فيما يلي مثال لبناء كائن، والذي يحتوي أيضًا على مصفوفة، وكتابته.
auto obj = glz::obj{ " pi " , 3.14 , " happy " , true , " name " , " Stephen " , " arr " , glz::arr{ " Hello " , " World " , 2 }};
std::string s{};
expect ( not glz::write_json (obj, s));
expect (s == R"( {"pi":3.14,"happy":true,"name":"Stephen","arr":["Hello","World",2]} )" );
هذا الأسلوب أسرع بكثير من
glz::json_t
لـ JSON العام. ولكنها قد لا تكون مناسبة لجميع السياقات.
glz::merge
يسمح للمستخدم بدمج أنواع كائنات JSON متعددة في كائن واحد.
glz::obj o{ " pi " , 3.141 };
std::map<std::string_view, int > map = {{ " a " , 1 }, { " b " , 2 }, { " c " , 3 }};
auto merged = glz::merge{o, map};
std::string s{};
glz::write_json (merged, s); // will write out a single, merged object
// s is now: {"pi":3.141,"a":0,"b":2,"c":3}
glz::merge
بتخزين الإشارات إلى القيم l لتجنب النسخ
راجع JSON العام لـ glz::json_t
.
glz:: json_t json{};
std::string buffer = R"( [5,"Hello World",{"pi":3.14}] )" ;
glz::read_json (json, buffer);
assert (json[ 2 ][ " pi " ].get< double >() == 3.14);
يعد Glaze بمثابة كتابة سريعة إلى std::string
كما هو الحال في الكتابة إلى مخزن مؤقت char خام. إذا كان لديك مساحة كافية في المخزن المؤقت الخاص بك، فيمكنك الكتابة إلى المخزن المؤقت الخام، كما هو موضح أدناه، ولكن لا يوصى بذلك.
glz::read_json(obj, buffer);
const auto n = glz::write_json(obj, buffer.data()).value_or(0);
buffer.resize(n);
تحدد البنية glz::opts
الإعدادات الاختيارية لوقت الترجمة للقراءة/الكتابة.
بدلاً من استدعاء glz::read_json(...)
، يمكنك الاتصال glz::read<glz::opts{}>(...)
وتخصيص الخيارات.
على سبيل المثال: glz::read<glz::opts{.error_on_unknown_keys = false}>(...)
إلى إيقاف تشغيل الأخطاء في المفاتيح غير المعروفة وتخطي العناصر ببساطة.
يمكن glz::opts
أيضًا التبديل بين التنسيقات:
glz::read<glz::opts{.format = glz::BEVE}>(...)
-> glz::read_beve(...)
glz::read<glz::opts{.format = glz::JSON}>(...)
-> glz::read_json(...)
يوضح الهيكل أدناه الخيارات المتاحة والسلوك الافتراضي.
struct opts {
uint32_t format = json;
bool comments = false ; // Support reading in JSONC style comments
bool error_on_unknown_keys = true ; // Error when an unknown key is encountered
bool skip_null_members = true ; // Skip writing out params in an object if the value is null
bool use_hash_comparison = true ; // Will replace some string equality checks with hash checks
bool prettify = false ; // Write out prettified JSON
bool minified = false ; // Require minified input for JSON, which results in faster read performance
char indentation_char = ' ' ; // Prettified JSON indentation char
uint8_t indentation_width = 3 ; // Prettified JSON indentation size
bool new_lines_in_arrays = true ; // Whether prettified arrays should have new lines for each element
bool shrink_to_fit = false ; // Shrinks dynamic containers to new size to save memory
bool write_type_info = true ; // Write type info for meta objects in variants
bool error_on_missing_keys = false ; // Require all non nullable keys to be present in the object. Use
// skip_null_members = false to require nullable members
bool error_on_const_read =
false ; // Error if attempt is made to read into a const value, by default the value is skipped without error
bool validate_skipped = false ; // If full validation should be performed on skipped values
bool validate_trailing_whitespace =
false ; // If, after parsing a value, we want to validate the trailing whitespace
uint8_t layout = rowwise; // CSV row wise output/input
// The maximum precision type used for writing floats, higher precision floats will be cast down to this precision
float_precision float_max_write_precision{};
bool bools_as_numbers = false ; // Read and write booleans with 1's and 0's
bool quoted_num = false ; // treat numbers as quoted or array-like types as having quoted numbers
bool number = false ; // read numbers as strings and write these string as numbers
bool raw = false ; // write out string like values without quotes
bool raw_string =
false ; // do not decode/encode escaped characters for strings (improves read/write performance)
bool structs_as_arrays = false ; // Handle structs (reading/writing) without keys, which applies
bool allow_conversions = true ; // Whether conversions between convertible types are
// allowed in binary, e.g. double -> float
bool partial_read =
false ; // Reads into only existing fields and elements and then exits without parsing the rest of the input
// glaze_object_t concepts
bool partial_read_nested = false ; // Advance the partially read struct to the end of the struct
bool concatenate = true ; // Concatenates ranges of std::pair into single objects when writing
bool hide_non_invocable =
true ; // Hides non-invocable members from the cli_menu (may be applied elsewhere in the future)
};
تحتوي العديد من خيارات وقت الترجمة هذه على أغلفة لتطبيق الخيار على حقل واحد فقط. انظر الأغلفة لمزيد من التفاصيل.
بشكل افتراضي، يتوافق Glaze تمامًا مع أحدث معايير JSON باستثناء حالتين مع الخيارات المرتبطة:
validate_skipped
يقوم هذا الخيار بالتحقق الكامل من صحة JSON للقيم التي تم تخطيها عند التحليل. لم يتم تعيين هذا افتراضيًا لأنه يتم عادةً تخطي القيم عندما لا يكون المستخدم مهتمًا بها، ولا يزال Glaze يتحقق من صحة المشكلات الرئيسية. ولكن هذا يجعل التخطي أسرع من خلال عدم الاهتمام بما إذا كانت القيم التي تم تخطيها متوافقة تمامًا مع JSON. على سبيل المثال، بشكل افتراضي، سيضمن Glaze أن الأرقام التي تم تخطيها تحتوي على جميع الأحرف الرقمية الصالحة، لكنه لن يتم التحقق من صحة مشكلات مثل الأصفار البادئة في الأرقام التي تم تخطيها ما لم يتم تشغيل validate_skipped
. أينما يقوم Glaze بتوزيع قيمة لاستخدامها، يتم التحقق من صحتها بالكامل.validate_trailing_whitespace
يتحقق هذا الخيار من صحة المسافة البيضاء الزائدة في المستند الذي تم تحليله. نظرًا لأن Glaze يوزع بنيات C++، فليست هناك حاجة عادةً إلى مواصلة التحليل بعد قراءة الكائن محل الاهتمام. قم بتشغيل هذا الخيار إذا كنت تريد التأكد من أن بقية المستند يحتوي على مسافة بيضاء صالحة، وإلا فسوف يتجاهل Glaze المحتوى بعد تحليل المحتوى محل الاهتمام. ملحوظة
لا يقوم Glaze تلقائيًا بتوحيد ترميز أحرف التحكم في الهروب (على سبيل المثال "x1f"
إلى "u001f"
)، لأن هذا يشكل خطر تضمين أحرف فارغة وأحرف أخرى غير مرئية في السلاسل. ستتم إضافة خيار وقت الترجمة لتمكين هذه التحويلات (مشكلة مفتوحة: تهرب unicode من الكتابة)، ولكنه لن يكون هو السلوك الافتراضي.
قد يكون من المفيد الإقرار بوجود مفاتيح في كائن لمنع الأخطاء، ومع ذلك قد لا تكون القيمة مطلوبة أو غير موجودة في C++. تتم معالجة هذه الحالات عن طريق تسجيل نوع glz::skip
مع بيانات التعريف.
struct S {
int i{};
};
template <>
struct glz ::meta<S> {
static constexpr auto value = object( " key_to_skip " , skip{}, &S::i);
};
std::string buffer = R"( {"key_to_skip": [1,2,3], "i": 7} )" ;
S s{};
glz::read_json (s, buffer);
// The value [1,2,3] will be skipped
expect (s.i == 7 ); // only the value i will be read into
تم تصميم Glaze للمساعدة في بناء واجهات برمجة التطبيقات العامة. في بعض الأحيان، يلزم عرض القيمة لواجهة برمجة التطبيقات (API)، ولكن ليس من المستحسن قراءة القيمة أو كتابتها بتنسيق JSON. هذه هي حالة استخدام glz::hide
.
يخفي glz::hide
القيمة من مخرجات JSON مع السماح بالوصول إلى واجهة برمجة التطبيقات (ومؤشر JSON).
struct hide_struct {
int i = 287 ;
double d = 3.14 ;
std::string hello = " Hello World " ;
};
template <>
struct glz ::meta<hide_struct> {
using T = hide_struct;
static constexpr auto value = object(&T::i, //
&T::d, //
" hello " , hide{&T::hello});
};
hide_struct s{};
auto b = glz::write_json(s);
expect (b == R"( {"i":287,"d":3.14} )" ); // notice that "hello" is hidden from the output
يمكنك تحليل أرقام JSON المقتبسة مباشرةً إلى أنواع مثل double
int
وما إلى ذلك باستخدام الغلاف glz::quoted
.
struct A {
double x;
std::vector< uint32_t > y;
};
template <>
struct glz ::meta<A> {
static constexpr auto value = object( " x " , glz::quoted_num<&A::x>, " y " , glz::quoted_num<&A::y>;
};
{
"x" : " 3.14 " ,
"y" : [ " 1 " , " 2 " , " 3 " ]
}
سيتم تحليل أرقام JSON المقتبسة مباشرة إلى double
و std::vector<uint32_t>
. تعمل الدالة glz::quoted
مع الكائنات والمصفوفات المتداخلة أيضًا.
يدعم Glaze خطوط JSON (أو Newline Delimited JSON) للأنواع المشابهة للمصفوفات (على سبيل المثال std::vector
و std::tuple
).
std::vector<std::string> x = { " Hello " , " World " , " Ice " , " Cream " };
std::string s = glz::write_ndjson(x).value_or( " error " );
auto ec = glz::read_ndjson(x, s);
راجع الدليل ext
للملحقات.
يتم توزيع Glaze بموجب ترخيص MIT باستثناء النماذج المضمنة:
--- استثناء اختياري للترخيص ---
كاستثناء، نتيجة لتجميع كود المصدر الخاص بك، إذا تم تضمين أجزاء من هذا البرنامج في نموذج كائن قابل للتنفيذ آليًا من كود المصدر هذا، يجوز لك إعادة توزيع هذه الأجزاء المضمنة في نموذج الكائن هذا دون تضمين حقوق الطبع والنشر والإذن إشعارات.