xpack
Bahasa inggris
- Digunakan untuk mengonversi antara struktur C++ dan json/xml/yaml/bson/mysql/sqlite
- Yang ada hanya file header, tidak ada file perpustakaan yang perlu dikompilasi, jadi tidak ada Makefile.
- Mendukung bson, bergantung pada
libbson-1.0
, perlu diinstal sendiri. Belum sepenuhnya diuji , silakan merujuk ke README untuk detailnya - Mendukung MySQL dan bergantung pada
libmysqlclient-dev
, yang perlu diinstal sendiri. Belum sepenuhnya diuji - Mendukung Sqlite dan bergantung pada libsqlite3, yang perlu diinstal sendiri. Belum sepenuhnya diuji
- Mendukung yaml, bergantung pada yaml-cpp, perlu diinstal sendiri. Belum sepenuhnya diuji
- Untuk detailnya, silakan lihat contoh
- Penggunaan dasar
- Dukungan kontainer
- BENDERA
- Alias
- bidang sedikit
- mewarisi
- menghitung
- Kodek khusus
- serikat
- tipe tidak terbatas
- susunan
- Kelas dan struktur pihak ketiga
- Format indentasi
- susunan XML
- CDATA
- Dukungan Qt
- MySQL
- Catatan penting
Penggunaan dasar
- Makro XPACK digunakan setelah struktur untuk memuat setiap variabel. XPACK juga memerlukan huruf. Silakan merujuk ke FLAG untuk mengetahui arti huruf yang berbeda.
- Gunakan xpack::json::encode untuk mengonversi struktur menjadi json
- Gunakan xpack::json::decode untuk mengonversi json menjadi struktur
# 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 ;
}
Dukungan kontainer
Saat ini kontainer berikut (std) didukung
- vektor
- mengatur
- daftar
- peta<string, T>
- map<integer, T> // Hanya JSON, XML tidak didukung
- unordered_map<string, T> (membutuhkan dukungan C++11)
- shared_ptr (membutuhkan dukungan C++11)
BENDERA
Di makro XPACK, variabel perlu disertakan dengan huruf, seperti XPACK(O(a,b)). Surat yang didukung saat ini adalah:
- X. Formatnya adalah X(F(flag1, flag2...), member1, member2,...) F berisi berbagai FLAG, yang saat ini didukung adalah:
- 0 tidak ada BENDERA
- Kelalaian OE, saat pengkodean, jika variabelnya 0 atau string kosong atau salah, informasi kunci yang sesuai tidak akan dihasilkan.
- EN kosong sebagai null, digunakan untuk pengkodean json. OE adalah bidang yang tidak menghasilkan kosong secara langsung, sedangkan EN menghasilkan null.
- M wajib, saat mendekode, jika bidang ini tidak ada, pengecualian akan dilempar, digunakan untuk beberapa bidang id.
- Atribut ATTR, saat menyandikan xml, masukkan nilai ke dalam atribut.
- SL satu baris, ketika json mengkodekan, untuk array, letakkan dalam satu baris
- C. Formatnya adalah C(customcodec, F(flag1,flags...), member1, member2,...) untuk fungsi pengkodean dan decoding khusus
- HAI. Setara dengan X(F(0), ...) tanpa BENDERA apa pun.
- M. Setara dengan X(F(M),...) yang menunjukkan bahwa bidang ini harus ada.
- A. Alias, A(member1, alias1, member2, alias2...), digunakan bila nama variabel dan kuncinya berbeda
- AF. Alias dengan FLAG, AF(F(flag1, flag2,...), member1, alias1, member2, alias2...)
- B. Bitfield, B(F(flag1, flag2, ...), member1, member2, ...) bitfield tidak mendukung alias
- SAYA. Warisan, I(baseclass1, baseclass2....), masukkan kelas induk di dalamnya
- E. menghitung:
- Jika compiler mendukung C++11, tidak perlu menggunakan E, dan enumerasi dapat ditempatkan di X/O/M/A.
- Jika tidak, enumerasi hanya dapat ditempatkan di E, dan alias tidak didukung.
Alias
- Digunakan untuk skenario dimana nama variabel dan nama kunci tidak konsisten
- Formatnya adalah A(variable, alias....) atau AF(F(flags), variabel, alias....), dan format aliasnya adalah format "xt:n"
- x mewakili alias global, t mewakili tipe (saat ini mendukung json, xml, dan bson), dan n mewakili alias di bawah tipe tersebut.
- Tidak diperlukan alias global. Misalnya
json:_id
legal. - Tidak diperlukan alias tipe. Misalnya,
_id
legal. - Jika ada tipe alias, gunakan tipe alias terlebih dahulu. Jika tidak, gunakan alias global. Jika tidak ada tipe alias, gunakan nama variabel.
# 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 ;
}
bidang sedikit
- Gunakan "B" untuk memasukkan variabel bitfield. Bitfield tidak mendukung alias.
# 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 ;
}
mewarisi
- Gunakan "I" untuk memasukkan kelas induk. Jika Anda perlu menggunakan variabel kelas induk, sertakan variabel tersebut. Jika Anda tidak membutuhkannya, Anda tidak perlu menyertakannya.
- Kelas induk dari kelas induk juga perlu disertakan, seperti kelas Base; kelas Base1:public Base; class Base2:public Base1; maka I(Base1, Base) diperlukan di Base2
- Kelas induk juga perlu mendefinisikan makro 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 ;
}
menghitung
- Jika kompiler mendukung C++11, enumerasinya memiliki nama yang sama dengan variabel biasa dan dapat ditempatkan di X/O/M/A.
- Jika tidak, perlu ditempatkan di E, formatnya 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 ;
}
Kodek khusus
Skenario aplikasi
- Beberapa tipe dasar ingin dikodekan dengan cara khusus, seperti menggunakan string untuk mengkodekan bilangan bulat/angka floating point.
- Beberapa tipe mungkin tidak ingin dikodekan satu per satu berdasarkan variabel struktur.
struct Time {
long ts; // unix timestamp
};
Kami tidak ingin menyandikannya ke dalam format {"ts":1218196800}, tetapi kami ingin menyandikannya ke dalam format "2008-08-08 20:00:00".
Ada dua cara di sini:
- Menggunakan xtype, Anda bisa merujuk pada contohnya
- Gunakan C untuk memasukkan variabel yang memerlukan pengkodean dan penguraian khusus (selanjutnya disebut sebagai metode C), Anda dapat merujuk pada contoh
Kedua metode pada dasarnya mengimplementasikan encode/decode sendiri, namun terdapat perbedaan berikut:
- xtype berada pada level tipe, yaitu, setelah suatu tipe dienkapsulasi dengan xtype, encode/decode yang disesuaikan akan berlaku pada tipe ini. xtype tidak dapat digunakan pada tipe dasar (int/string, dll.)
- Metode C dapat mendukung tipe dasar (int/string, dll.) dan tipe non-dasar, tetapi hanya bekerja pada variabel yang terdapat dalam C, seperti int a; int b; ), b) ;Kemudian a masih menggunakan codec default, dan b menggunakan codec khusus.
- xtype lebih diutamakan daripada makro XPACK, yaitu jika xtype didefinisikan, encode/decode xtype akan digunakan terlebih dahulu.
- Metode C lebih diutamakan daripada xtype, yaitu variabel yang terdapat dalam C pasti akan menggunakan metode pengkodean dan decoding yang ditentukan dalam C.
Dengan menggunakan kedua fitur ini, Anda dapat mencapai beberapa kontrol pengkodean dan __x_pack_decode
kode yang lebih fleksibel. Misalnya, contoh ini mengimplementasikan fungsi pengkodean berdasarkan kondisi variabel. Jika Sub.type==1, enkodekan __x_pack_encode
, jika tidak, enkodekan seq2 XPACK Fungsi decode/encode yang ditambahkan oleh makro ke struktur, fungsi pengkodean dan dekode khusus dapat memanggil fungsi pengkodean dan dekode default xpack melalui fungsi-fungsi ini.
serikat
Anda dapat menggunakan codec khusus untuk memproses penyatuan, silakan lihat contohnya
susunan
- Saat mendekode, jika jumlah elemen melebihi panjang array, maka akan terpotong.
- Array char diproses seolah-olah memiliki terminator
# 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 ;
}
tipe tidak terbatas
- Skenario di mana skema json tidak pasti
- Gunakan xpack::JsonData untuk menerima informasi ini
- Anda dapat merujuk pada contoh
- Metode utama xpack::JsonData adalah:
- Jenis. digunakan untuk mendapatkan tipe
- Rangkaian fungsi IsXXX. Digunakan untuk menentukan apakah itu tipe tertentu, pada dasarnya setara dengan return Type()==xxxx;
- Fungsi seri GetXXX. Digunakan untuk mengekstrak nilai.
- Bodoh kelebihan beban. Digunakan untuk menentukan apakah itu adalah JsonData legal.
- Ukuran. Digunakan untuk menentukan jumlah elemen dalam tipe array
-
operator [](size_t index)
digunakan untuk mendapatkan elemen indeks array (mulai dari 0) -
operator [](const char *key)
digunakan untuk mendapatkan elemen tipe Objek berdasarkan kunci - Mulai. Digunakan untuk melintasi elemen Object, mengambil yang pertama.
- Berikutnya. Gunakan dengan Begin untuk mendapatkan elemen berikutnya.
- Kunci. Konfigurasikan Mulai dan Berikutnya untuk digunakan, dan dapatkan Kunci saat melakukan traversing
Kelas dan struktur pihak ketiga
- Gunakan XPACK_OUT alih-alih XPACK untuk memasukkan variabel
- XPACK_OUT harus didefinisikan dalam namespace global
# 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 ;
}
Format indentasi
- Json/xml yang dihasilkan oleh encode secara default tidak menjorok ke dalam dan cocok untuk penggunaan program.
- Dua parameter terakhir dari kontrol encode
- indentCount mewakili jumlah karakter untuk indentasi, <0 mewakili tidak ada indentasi, 0 mewakili baris baru tetapi tidak ada indentasi.
- indentChar mewakili karakter yang menjorok ke dalam, menggunakan spasi atau tab
susunan XML
- Array menggunakan nama variabel sebagai label elemen secara default, seperti "ids":[1,2,3], dan xml yang sesuai adalah:
< ids >
< ids >1</ ids >
< ids >2</ ids >
< ids >3</ ids >
</ ids >
- Anda dapat menggunakan alias untuk mengontrol label elemen array, seperti A(ids,"xml:ids,vl@id"), vl diikuti oleh @xx, xx adalah label array, dan dihasilkan hasilnya adalah:
< ids >
< id >1</ id >
< id >2</ id >
< id >3</ id >
</ ids >
- Jika Anda ingin array diperluas secara langsung alih-alih membungkusnya dengan lapisan di luar, Anda dapat menggunakan alias plus flag "sbs" untuk mencapai hal ini, seperti A ( ids, "xml:ids,sbs"). Tag sbs hanya dapat digunakan untuk array. Lainnya Penggunaan lokal mungkin macet
< ids >1</ ids >
< ids >2</ ids >
< ids >3</ ids >
CDATA
- Untuk tipe CDATA, Anda perlu menggunakan flag "cdata" untuk mengimplementasikannya, seperti A(data, "xml:data,cdata")
- cdata hanya dapat diterima menggunakan std::string
- Jika xml yang sesuai dengan variabel bukan struktur CDATA, maka akan diproses sebagai string normal. Misalnya,
<data>hello</data>
juga dapat diurai dengan sukses.
Dukungan Qt
- Ubah config.h dan aktifkan makro XPACK_SUPPORT_QT (atau aktifkan di opsi kompilasi)
- Saat ini mendukung QString/QMap/QList/QVector
MySQL
- Saat ini hanya decode yang didukung, dan encode belum didukung.
- Belum sepenuhnya diuji, gunakan dengan hati-hati
- Jenis yang didukung saat ini adalah:
- rangkaian. Tes sederhana.
- Tipe bilangan bulat. Tes sederhana.
- Tipe titik mengambang. Tidak diuji.
- Gunakan tipe integer (seperti time_t) untuk menerima TIME/DATETIME/TIMESTAMP. Tidak diuji.
- Konversi tipe khusus, is_xpack_mysql_xtype, mirip dengan xtype. Tidak diuji.
- Ada dua API (xpack::mysql::):
-
static void decode(MYSQL_RES *result, T &val)
- Digunakan untuk mengubah MYSQL_RES menjadi struktur atau vektor<>. Jika non-vektor, hanya baris pertama yang akan dikonversi.
-
static void decode(MYSQL_RES *result, const std::string&field, T &val)
- Digunakan untuk mengurai bidang tertentu, digunakan dalam skenario di mana Anda hanya ingin mendapatkan konten bidang tertentu, seperti pilih id dari tabel saya di mana nama = lilei, dan hanya ingin mendapatkan informasi id. val mendukung vektor
Catatan penting
- Cobalah untuk tidak memulai nama variabel dengan __x_pack, jika tidak maka akan menimbulkan konflik dengan perpustakaan.
- vc6 tidak didukung.
- msvc belum melakukan banyak tes, hanya tes sederhana di tahun 2019.
- Serialisasi dan deserialisasi json menggunakan rapidjson.
- Deserialisasi xml menggunakan rapidxml
- Serialisasi xml saya tulis sendiri tanpa mengacu pada RFC, jadi mungkin berbeda dari standar.
- Jika Anda memiliki pertanyaan, Anda dapat bergabung dengan grup QQ 878041110