xpack
إنجليزي
- يستخدم للتحويل بين بنيات C++ وjson/xml/yaml/bson/mysql/sqlite
- لا يوجد سوى ملفات رأسية، ولا يلزم تجميع ملفات المكتبة، لذلك لا يوجد ملف Makefile.
- يدعم bson، ويعتمد على
libbson-1.0
، ويجب تثبيته بنفسك. لم يتم اختباره بشكل كامل ، يرجى الرجوع إلى README للحصول على التفاصيل - يدعم MySQL ويعتمد على
libmysqlclient-dev
، والذي يجب تثبيته بنفسك. لم يتم اختباره بالكامل - يدعم Sqlite ويعتمد على libsqlite3 الذي يجب تثبيته بنفسك. لم يتم اختباره بالكامل
- يدعم yaml، ويعتمد على yaml-cpp، ويجب تثبيته بنفسك. لم يتم اختباره بالكامل
- لمزيد من التفاصيل، يرجى الرجوع إلى المثال
- الاستخدام الأساسي
- دعم الحاويات
- علَم
- الاسم المستعار
- مجال قليلا
- يرث
- تعداد
- برنامج الترميز المخصص
- الاتحاد
- نوع غير محدد
- صفيف
- فئات وهياكل الطرف الثالث
- تنسيق المسافة البادئة
- مصفوفة XML
- CDATA
- دعم كيو تي
- ماي إس كيو إل
- ملاحظة هامة
الاستخدام الأساسي
- يتم استخدام الماكرو XPACK بعد البنية لاحتواء كل متغير، كما يتطلب XPACK حرفًا.
- استخدم xpack::json::encode لتحويل البنية إلى json
- استخدم xpack::json::decode لتحويل json إلى بنية
# include < iostream >
# include " xpack/json.h " // Json包含这个头文件,xml则包含xpack/xml.h
using namespace std ;
struct User {
int id;
string name;
XPACK (O(id, name)); // 添加宏定义XPACK在结构体定义结尾
};
int main ( int argc, char *argv[]) {
User u;
string data = " { " id " :12345, " name " : " xpack " } " ;
xpack::json::decode (data, u); // json转结构体
cout<<u. id << ' ; ' <<u. name <<endl;
string json = xpack::json::encode (u); // 结构体转json
cout<<json<<endl;
return 0 ;
}
دعم الحاويات
حاليًا يتم دعم الحاويات التالية (std).
- ناقلات
- تعيين
- قائمة
- خريطة <سلسلة، T>
- Map<integer, T> // JSON فقط، XML غير مدعوم
- unordered_map<string, T> (يتطلب دعم C++ 11)
- Shared_ptr (يتطلب دعم C++ 11)
علَم
في الماكرو XPACK، يجب تضمين المتغيرات بأحرف، مثل XPACK(O(a,b)). يمكن أن يحتوي XPACK على أحرف متعددة، ويمكن أن يحتوي كل حرف على متغيرات متعددة. الحروف المدعومة حاليا هي:
- X. التنسيق هو X(F(flag1, flag2...), member1, member2,...) F يحتوي على أعلام مختلفة، المدعومة حاليًا هي:
- 0 لا يوجد علم
- OE مهمل، عند الترميز، إذا كان المتغير 0 أو سلسلة فارغة أو خطأ، فلن يتم إنشاء معلومات المفتاح المقابلة.
- EN فارغ كقيمة خالية، يُستخدم لتشفير json. OE هو حقل لا يُنشئ فارغًا مباشرة، بينما EN يُنشئ حقلًا فارغًا.
- M إلزامي، عند فك التشفير، إذا لم يكن هذا الحقل موجودًا، فسيتم طرح استثناء يستخدم لبعض حقول المعرف.
- سمة ATTR، عند تشفير ملف XML، ضع القيمة في السمة.
- سطر واحد SL، عندما يتم تشفير json، بالنسبة للمصفوفات، ضعها في سطر واحد
- ج. التنسيق هو C(customcodec, F(flag1,flags...), member1, member2,...) لوظائف الترميز وفك التشفير المخصصة للحصول على التفاصيل، يرجى الرجوع إلى برنامج الترميز المخصص
- يا. أي ما يعادل X(F(0)، ...) بدون أي علامة.
- م. أي ما يعادل X(F(M),...) يشير إلى أن هذه الحقول يجب أن تكون موجودة.
- أ. الاسم المستعار، A( member1, alias1, member2, alias2...)، يُستخدم عندما تكون أسماء المتغيرات وأسماء المفاتيح مختلفة
- بالعربية. الاسم المستعار مع FLAG، AF(F(flag1، flag2،...)، member1، alias1، member2، alias2...)
- ب. Bitfield, B(F(flag1, flag2, ...), member1, member2, ...) حقل البت لا يدعم الأسماء المستعارة
- أنا. الميراث، أنا (baseclass1، baseclass2....) أضع الفئة الأصل فيه
- ه. تعداد:
- إذا كان المترجم يدعم C++ 11، ليست هناك حاجة لاستخدام E، ويمكن وضع التعداد في X/O/M/A.
- بخلاف ذلك، لا يمكن وضع التعداد إلا في E، ولا يتم دعم الأسماء المستعارة.
الاسم المستعار
- يُستخدم للسيناريوهات التي يكون فيها اسم المتغير واسم المفتاح غير متناسقين
- التنسيق هو A(متغير، اسم مستعار....) أو AF(F(أعلام)، متغير، اسم مستعار....)، وتنسيق الاسم المستعار هو تنسيق "xt:n"
- يمثل x الاسم المستعار العام، ويمثل t النوع (يدعم حاليًا json وxml وbson)، ويمثل n الاسم المستعار الموجود أسفل النوع.
- ليست هناك حاجة لاسم مستعار عالمي، على سبيل المثال
json:_id
قانوني. - ليست هناك حاجة للأسماء المستعارة للنوع، على سبيل المثال،
_id
قانوني. - إذا كان هناك اسم مستعار للنوع، فاستخدم الاسم المستعار للنوع أولاً. وإلا، فاستخدم الاسم المستعار العام. إذا لم يكن هناك اسم مستعار للنوع، فاستخدم اسم المتغير.
# include < iostream >
# include " xpack/json.h "
using namespace std ;
struct Test {
long uid;
string name;
XPACK (A(uid, " id " ), O(name)); // "uid"的别名是"id"
};
int main ( int argc, char *argv[]) {
Test t;
string json= " { " id " :123, " name " : " Pony " } " ;
xpack::json::decode (json, t);
cout<<t. uid <<endl;
return 0 ;
}
مجال قليلا
- استخدم "B" لتضمين متغيرات حقل البت التي لا تدعم الأسماء المستعارة.
# include < iostream >
# include " xpack/json.h "
using namespace std ;
struct Test {
short ver: 8 ;
short len: 8 ;
string name;
XPACK (B(F( 0 ), ver, len), O(name));
};
int main ( int argc, char *argv[]) {
Test t;
string json= " { " ver " :4, " len " :20, " name " : " IPv4 " } " ;
xpack::json::decode (json, t);
cout<<t. ver <<endl;
cout<<t. len <<endl;
return 0 ;
}
يرث
- استخدم "I" لتضمين الفئة الأصل. إذا كنت بحاجة إلى استخدام متغيرات الفئة الأصل، قم بتضمينها. وإذا لم تكن بحاجة إليها، فلن تحتاج إلى تضمينها.
- يجب أيضًا تضمين الفئة الأصلية للفئة الأصلية، مثل الفئة Base؛ class Base1:public Base؛ class Base2:public Base1؛ ثم I(Base1, Base) مطلوب في Base2
- تحتاج الفئة الأصل أيضًا إلى تعريف الماكرو XPACK/XPACK_OUT.
# include < iostream >
# include " xpack/json.h "
using namespace std ;
struct P1 {
string mail;
XPACK (O(mail));
};
struct P2 {
long version;
XPACK (O(version));
};
struct Test : public P1 , public P2 {
long uid;
string name;
XPACK (I(P1, P2), O(uid, name));
};
int main ( int argc, char *argv[]) {
Test t;
string json= " { " mail " : " [email protected] " , " version " :2019, " id " :123, " name " : " Pony " } " ;
xpack::json::decode (json, t);
cout<<t. mail <<endl;
cout<<t. version <<endl;
return 0 ;
}
تعداد
- إذا كان المترجم يدعم C++ 11، فإن التعداد له نفس اسم المتغير العادي ويمكن وضعه في X/O/M/A.
- بخلاف ذلك، يجب وضعه في E، التنسيق هو E(F(...)، member1، member2، ...)
# include < iostream >
# include " xpack/json.h "
using namespace std ;
enum Enum {
X = 0 ,
Y = 1 ,
Z = 2 ,
};
struct Test {
string name;
Enum e;
XPACK (O(name), E(F( 0 ), e));
};
int main ( int argc, char *argv[]) {
Test t;
string json= " { " name " : " IPv4 " , " e " :1} " ;
xpack::json::decode (json, t);
cout<<t. name <<endl;
cout<<t. e <<endl;
return 0 ;
}
برنامج الترميز المخصص
سيناريوهات التطبيق
- تريد بعض الأنواع الأساسية أن يتم تشفيرها بطريقة مخصصة، مثل استخدام السلاسل لتشفير الأعداد الصحيحة/أرقام الفاصلة العائمة.
- قد لا ترغب بعض الأنواع في التشفير واحدًا تلو الآخر وفقًا لمتغيرات البنية، على سبيل المثال، إذا تم تعريف بنية زمنية:
struct Time {
long ts; // unix timestamp
};
لا نريد تشفيره بالتنسيق {"ts":1218196800}، ولكننا نريد تشفيره بالتنسيق "2008-08-08 20:00:00".
هناك طريقتان هنا:
- باستخدام xtype، يمكنك الرجوع إلى المثال
- استخدم لغة C لتضمين المتغيرات التي تتطلب تشفيرًا وفك تشفير مخصصًا (يشار إليها فيما يلي باسم طريقة C)، يمكنك الرجوع إلى المثال
تقوم كلتا الطريقتين بتنفيذ التشفير/فك التشفير بشكل أساسي من تلقاء نفسها، ولكن هناك الاختلافات التالية:
- يوجد xtype على مستوى النوع، أي أنه بمجرد تغليف النوع بـ xtype، فإن التشفير/فك التشفير المخصص سيصبح ساري المفعول على هذا النوع. لا يمكن استخدام xtype على الأنواع الأساسية (int/string، وما إلى ذلك)
- يمكن أن تدعم طريقة C الأنواع الأساسية (int/string، وما إلى ذلك) والأنواع غير الأساسية، ولكنها تعمل فقط على المتغيرات الموجودة في لغة C، مثل int a; ), b) ;ثم يستمر a في استخدام برنامج الترميز الافتراضي، ويستخدم b برنامج الترميز المخصص.
- يكون لـ xtype الأسبقية على ماكرو XPACK، أي أنه إذا تم تعريف xtype، فسيتم استخدام تشفير/فك تشفير xtype أولاً.
- طريقة C لها الأسبقية على xtype، أي أن المتغيرات الموجودة في لغة C ستستخدم بالتأكيد طرق التشفير وفك التشفير المحددة في لغة C.
باستخدام هاتين الميزتين، يمكنك تحقيق بعض عناصر التحكم في التشفير وفك التشفير الأكثر مرونة. على سبيل __x_pack_encode
، يطبق هذا المثال وظيفة تشفير بناءً على شروط متغيرة. إذا كان Sub.type==1، فقم بتشفير __x_pack_decode
، وإلا قم بتشفير seq2 XPACK يمكن لوظائف فك التشفير/التشفير التي يضيفها الماكرو إلى البنية، ووظائف التشفير وفك التشفير المخصصة، استدعاء وظائف التشفير وفك التشفير الافتراضية لـ xpack من خلال هذه الوظائف.
الاتحاد
يمكنك استخدام برامج الترميز المخصصة لمعالجة الاتحادات، يرجى الرجوع إلى المثال
صفيف
- عند فك التشفير، إذا تجاوز عدد العناصر طول المصفوفة، فسيتم اقتطاعها.
- تتم معالجة صفائف Char كما لو كانت تحتوي على فاصل
# include < iostream >
# include " xpack/json.h "
using namespace std ;
struct Test {
char name[ 64 ];
char email[ 64 ];
XPACK (O(name, email));
};
int main ( int argc, char *argv[]) {
Test t;
string json= " { " name " : " Pony " , " email " : " [email protected] " } " ;
xpack::json::decode (json, t);
cout<<t. name <<endl;
cout<<t. email <<endl;
return 0 ;
}
نوع غير محدد
- السيناريوهات التي يكون فيها مخطط json غير مؤكد
- استخدم xpack::JsonData لتلقي هذه المعلومات
- يمكنك الرجوع إلى الأمثلة
- الطرق الرئيسية لـ xpack::JsonData هي:
- يكتب. تستخدم للحصول على النوع
- سلسلة IsXXX من الوظائف. يُستخدم لتحديد ما إذا كان نوعًا معينًا، وهو ما يعادل بشكل أساسي إرجاع Type()==xxxx;
- وظائف سلسلة GetXXX. تستخدم لاستخراج القيم.
- الزائد منطقي. يستخدم لتحديد ما إذا كان JsonData قانونيًا.
- مقاس. يستخدم لتحديد عدد العناصر في نوع المصفوفة
- يتم استخدام
operator [](size_t index)
للحصول على عنصر الفهرس الخاص بالمصفوفة (بدءًا من 0) - يتم استخدام
operator [](const char *key)
للحصول على عناصر من النوع Object بناءً على المفتاح - يبدأ. يستخدم لاجتياز عناصر الكائن، مع أخذ العنصر الأول.
- التالي. استخدمه مع Begin للحصول على العنصر التالي.
- مفتاح. قم بتكوين "البدء" و"التالي" للاستخدام، واحصل على المفتاح عند العبور
فئات وهياكل الطرف الثالث
- استخدم XPACK_OUT بدلاً من XPACK لتضمين المتغيرات
- يجب تعريف XPACK_OUT في مساحة الاسم العامة
# include < sys/time.h >
# include < iostream >
# include " xpack/json.h "
using namespace std ;
/*
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};
*/
// timeval is thirdparty struct
XPACK_OUT ( timeval , O(tv_sec, tv_usec));
struct T {
int a;
string b;
timeval t;
XPACK (O(a, b, t));
};
int main ( int argc, char *argv[]) {
T t;
T r;
t. a = 123 ;
t. b = " xpack " ;
t. t . tv_sec = 888 ;
t. t . tv_usec = 999 ;
string s = xpack::json::encode (t);
cout<<s<<endl;
xpack::json::decode (s, r);
cout<<r. a << ' , ' <<r. b << ' , ' <<r. t . tv_sec << ' , ' <<r. t . tv_usec <<endl;
return 0 ;
}
تنسيق المسافة البادئة
- لا يتم وضع مسافة بادئة لملف json/xml الذي تم إنشاؤه بواسطة التشفير بشكل افتراضي، وهو مناسب لاستخدام البرنامج، إذا قرأه الأشخاص، فيمكن وضع مسافة بادئة له.
- المعلمتان الأخيرتان للتحكم في التشفير
- يمثل indentCount عدد الأحرف للمسافة البادئة، ويمثل <0 عدم وجود مسافة بادئة، ويمثل 0 سطرًا جديدًا ولكن بدون مسافة بادئة.
- يمثل indentChar الحرف ذي المسافة البادئة، باستخدام المسافات أو علامات التبويب
مصفوفة XML
- تستخدم المصفوفات أسماء المتغيرات كتسميات للعناصر بشكل افتراضي، مثل "ids":[1,2,3]، وملف XML المقابل هو:
< ids >
< ids >1</ ids >
< ids >2</ ids >
< ids >3</ ids >
</ ids >
- يمكنك استخدام الأسماء المستعارة للتحكم في تسميات عناصر المصفوفة، مثل A(ids,"xml:ids,vl@id")، وvl متبوعة بـ @xx، وxx هي تسمية المصفوفة، والاسم الذي تم إنشاؤه النتيجة هي:
< ids >
< id >1</ id >
< id >2</ id >
< id >3</ id >
</ ids >
- إذا كنت تريد توسيع المصفوفة مباشرةً بدلاً من تغليفها بطبقة خارجية، فيمكنك استخدام الاسم المستعار بالإضافة إلى علامة "sbs" لتحقيق ذلك، مثل A ( ids, "xml:ids,sbs"). لا يمكن استخدام علامة sbs إلا للصفائف. وقد يتعطل الاستخدام المحلي للآخرين
< ids >1</ ids >
< ids >2</ ids >
< ids >3</ ids >
CDATA
- بالنسبة لنوع CDATA، تحتاج إلى استخدام علامة "cdata" للتنفيذ، مثل A(data, "xml:data,cdata")
- لا يمكن تلقي بيانات cdata إلا باستخدام std::string
- إذا لم يكن ملف XML المطابق للمتغير عبارة عن بنية CDATA، فستتم معالجته كسلسلة عادية. على سبيل المثال، يمكن أيضًا تحليل
<data>hello</data>
بنجاح.
دعم كيو تي
- قم بتعديل config.h وتمكين الماكرو XPACK_SUPPORT_QT (أو تمكينه في خيار الترجمة)
- يدعم حاليًا QString/QMap/QList/QVector
ماي إس كيو إل
- حاليًا يتم دعم فك التشفير فقط، ولا يتم دعم التشفير بعد.
- لم يتم اختباره بشكل كامل، استخدمه بحذر
- الأنواع المدعومة حاليًا هي:
- خيط. اختبار بسيط.
- نوع عدد صحيح. اختبار بسيط.
- نوع النقطة العائمة. لم يتم اختباره.
- استخدم النوع الصحيح (مثل time_t) لتلقي الوقت/التاريخ/الوقت/التوقيت الزمني. لم يتم اختباره.
- تحويل النوع المخصص، is_xpack_mysql_xtype، مشابه لـ xtype. لم يتم اختباره.
- هناك نوعان من واجهات برمجة التطبيقات (xpack::mysql::):
-
static void decode(MYSQL_RES *result, T &val)
- يُستخدم لتحويل MYSQL_RES إلى بنية أو متجه<> إذا لم يكن متجهًا، فسيتم تحويل الصف الأول فقط.
-
static void decode(MYSQL_RES *result, const std::string&field, T &val)
- يُستخدم لتحليل حقل معين، ويستخدم في السيناريوهات التي تريد فيها الحصول على محتوى حقل معين فقط، مثل تحديد المعرف من الجدول mytable حيث الاسم = lilei، وتريد فقط الحصول على معلومات المعرف. فال يدعم المتجه
ملاحظة هامة
- حاول ألا تبدأ اسم المتغير بـ __x_pack، وإلا فقد يتعارض مع المكتبة.
- vc6 غير مدعوم.
- لم يقم msvc بإجراء العديد من الاختبارات، فقط اختبارات بسيطة في عام 2019.
- يستخدم التسلسل وإلغاء التسلسل لـ json Rapidjson.
- إلغاء تسلسل XML يستخدم RapidXML
- لقد قمت بكتابة تسلسل XML بنفسي دون الرجوع إلى RFC، لذلك قد يكون مختلفًا عن المعيار.
- إذا كان لديك أي أسئلة، يمكنك الانضمام إلى مجموعة QQ 878041110