xpack
Английский
- Используется для преобразования между структурами C++ и json/xml/yaml/bson/mysql/sqlite.
- Есть только файлы заголовков, файлы библиотек компилировать не нужно, поэтому Makefile нет.
- Поддерживает bson, зависит от
libbson-1.0
, необходимо установить самостоятельно. Не полностью протестировано , подробности см. в README. - Поддерживает MySQL и зависит от
libmysqlclient-dev
, который необходимо установить самостоятельно. Не полностью протестировано - Поддерживает Sqlite и зависит от libsqlite3, которую необходимо установить самостоятельно. Не полностью протестировано
- Поддерживает yaml, зависит от yaml-cpp, необходимо установить самостоятельно. Не полностью протестировано
- Подробности смотрите в примере
- Основное использование
- Поддержка контейнеров
- ФЛАГ
- Псевдоним
- битовое поле
- наследовать
- перечислять
- Пользовательский кодек
- союз
- неопределенный тип
- множество
- Сторонние классы и структуры
- Отступ формата
- XML-массив
- CDATA
- Поддержка Qt
- MySQL
- Важное примечание
Основное использование
- Макрос XPACK используется после структуры, содержащей каждую переменную. Для XPACK также требуется буква. Значения различных букв см. в разделе FLAG.
- Используйте 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)
- вектор
- набор
- список
- карта<строка, Т>
- map<integer, T> // только JSON, XML не поддерживается
- unordered_map<string, T> (требуется поддержка C++11)
- shared_ptr (требуется поддержка C++11)
ФЛАГ
В макросе XPACK переменные должны включаться вместе с буквами, например XPACK(O(a,b)). В настоящее время поддерживаются следующие буквы:
- Х. Формат: X(F(flag1, flag2...),member1,member2,...). F содержит различные флаги, в настоящее время поддерживаются следующие:
- 0 нет ФЛАГА
- OE omitempty: при кодировании, если переменная равна 0, пустой строке или ложна, соответствующая ключевая информация не будет сгенерирована.
- EN пусто как нулевое значение, используется для кодирования json. OE — это поле, которое не генерирует пустое значение напрямую, тогда как EN генерирует нулевое значение.
- M обязательно, при декодировании, если это поле не существует, будет выдано исключение, используемое для некоторых полей id.
- Атрибут 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...)
- Б. Битовое поле, B(F(флаг1, флаг2, ...), член1, член2, ...) битовое поле не поддерживает псевдонимы
- Я. Наследование, я (базовый класс1, базовый класс2....), помещаю в него родительский класс
- Э. перечислить:
- Если компилятор поддерживает 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», чтобы включить родительский класс. Если вам нужно использовать переменные родительского класса, включите их. Если они вам не нужны, вам не нужно их включать.
- Также необходимо включить родительский класс родительского класса, например class Base; class Base1:public Base; class Base2:public Base1, тогда в Base2 требуется I(Base1, Base);
- Родительский класс также должен определить макрос 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; int O(a), C(custome_int, F(0). ), b) ;Тогда a по-прежнему использует кодек по умолчанию, а b использует собственный кодек.
- xtype имеет приоритет над макросом XPACK, то есть, если xtype определен, сначала будет использоваться кодирование/декодирование xtype.
- Метод C имеет приоритет над xtype, то есть переменные, содержащиеся в C, обязательно будут использовать методы кодирования и декодирования, указанные в C.
Используя эти две функции, вы можете добиться более гибкого управления кодированием и __x_pack_decode
. Например, в этом примере реализована функция кодирования на основе условий переменных. Если Sub.type==1, кодируйте __x_pack_encode
, в противном случае кодируйте seq2. XPACK Функции декодирования/кодирования, добавленные макросом в структуру, пользовательские функции кодирования и декодирования могут вызывать через эти функции функции кодирования и декодирования xpack по умолчанию.
союз
Вы можете использовать собственные кодеки для обработки объединений, см. пример.
множество
- Если при декодировании количество элементов превышает длину массива, он будет усечен.
- Массивы символов обрабатываются так, как если бы они имели терминатор .
# 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. Используется для определения того, относится ли это к определенному типу, что в основном эквивалентно return Type()==xxxx;
- Функции серии GetXXX. Используется для извлечения значений.
- Перегрузка bool. Используется для определения того, является ли это допустимым JsonData.
- Размер. Используется для определения количества элементов в типе массива.
-
operator [](size_t index)
используется для получения индексного элемента массива (начиная с 0) -
operator [](const char *key)
используется для получения элементов типа Object на основе ключа - Начинать. Используется для обхода элементов 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, созданный с помощью encode, по умолчанию не имеет отступов и подходит для использования в программе. Если его читают люди, в нем могут быть отступы.
- Последние два параметра управления кодированием
- 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>
также может быть успешно проанализировано.
Поддержка Qt
- Измените config.h и включите макрос XPACK_SUPPORT_QT (или включите его в параметрах компиляции).
- В настоящее время поддерживает QString/QMap/QList/QVector.
MySQL
- В настоящее время поддерживается только декодирование, а кодирование еще не поддерживается.
- Не полностью протестировано, используйте с осторожностью
- В настоящее время поддерживаются следующие типы:
- нить. Простой тест.
- Целочисленный тип. Простой тест.
- Тип с плавающей запятой. Не проверено.
- Используйте целочисленный тип (например, time_t) для получения TIME/DATETIME/TIMESTAMP. Не проверено.
- Пользовательское преобразование типов is_xpack_mysql_xtype, аналогичное xtype. Не проверено.
- Существует два API (xpack::mysql::):
-
static void decode(MYSQL_RES *result, T &val)
- Используется для преобразования MYSQL_RES в структуру или вектор <>. Если он не векторный, будет преобразована только первая строка.
-
static void decode(MYSQL_RES *result, const std::string&field, T &val)
- Используется для анализа определенного поля, используется в сценариях, где вы хотите получить только содержимое определенного поля, например, выберите id из mytable, где name = lilei, и просто хотите получить информацию об идентификаторе. вал поддерживает вектор
Важное примечание
- Старайтесь не начинать имя переменной с __x_pack, иначе может возникнуть конфликт с библиотекой.
- vc6 не поддерживается.
- msvc не проводил много тестов, только простые тесты в 2019 году.
- Сериализация и десериализация json использует RapidJSON.
- Десериализация XML использует RapidXML.
- Сериализацию xml написал я без ссылки на RFC, поэтому она может отличаться от стандартной.
- Если у вас есть какие-либо вопросы, вы можете присоединиться к группе QQ 878041110.