-
Notifications
You must be signed in to change notification settings - Fork 7
SimpleJson
Для описания сериализации простых типов используется конструкция value:
template<typename T, int R = -1>
struct value
{
typedef T target;
typedef serializerT< value<char, R> > serializer;
};-
T, target - bool, интегральный тип, тип с плавающей точкой,
std::string,std::vector<char>илиchar[N] - R - в зависимости от контекста размер резерва для контейнера строк или формат сериализации для чисел с плавающей точкой
- serializer - сериализатор/десериализатор
Допустимые значения R и поддерживаемые типы:
| Тип | Допустимые значения R | Примечание |
|---|---|---|
bool |
R=-1 | R не используется, прочие значения не допустимы |
char |
R=-1 | -"- |
unsigned char |
R=-1 | -"- |
short |
R=-1 | -"- |
unsigned short |
R=-1 | -"- |
int |
R=-1 | -"- |
unsigned int |
R=-1 | -"- |
long int |
R=-1 | -"- |
unsigned long |
R=-1 | -"- |
long long |
R=-1 | -"- |
unsigned long long |
R=-1 | -"- |
float |
R>=0 | При R==0 - сериализация в формате с плавающей точкой. При R>0 - сериализация в формате с фиксированной точкой, где R - число знаков после запятой |
double |
R>=0 | -"- |
long double |
R>=0 | -"- |
std::string |
R>=0 | R - резервирование при десериализации (std::string::reserve(R)). По умолчанию, при R==-1, резерв 64 байта |
std::vector<char> |
R>=0 | -"- |
char[N] |
R=-1 | R не используется, прочие значения не допустимы |
Реализует сериализацию значений типа bool в true или false. Десериализация возможна также только строго из этих значений.
/* Правильный формат. Вывод: true */
bool flag = false;
std::string json="true";
::wjson::value<bool>::serializer()(flag, json.begin(), json.end(), 0);
std::cout << std::boolalpha;
std::cout << flag << std::endl;
/* Неправильный формат. Вывод: false */
flag = false;
json="1";
::wjson::value<bool>::serializer()(flag, json.begin(), json.end(), 0);
std::cout << flag << std::endl;
/* Неправильный формат с обработкой ошибки. Вывод: false: Invalid Bool*/
flag = false;
json="1";
::wjson::json_error e;
::wjson::value<bool>::serializer()(flag, json.begin(), json.end(), &e);
std::cout << flag << ": ";
std::cout << ::wjson::strerror::message(e) << std::endl;Вывод:
true
false
false: Invalid Bool
Десериализация будет валидной, если первым символом в строке будет цифра. При десериализации переполнение не отслеживается и будет производиться до первой не цифры.
Пример с переполнением short:
typedef ::wjson::value<short>::serializer serializer_t;
short value = 0;
std::string json="12356789XYZ";
::wjson::json_error e;
std::string::iterator itr = serializer_t()(value, json.begin(), json.end(), &e );
std::cout << value << ": ";
std::cout << ::wjson::strerror::message(e) << std::endl;
std::cout << "Tail: " << std::string( itr, json.end() ) << std::endl;
serializer_t()(value, std::ostreambuf_iterator<char>(std::cout));
std::cout << std::endl; Вывод:
-29515: Valid JSON
Tail: XYZ
-29515
Примечание: При сериализации/десериализации используется std::stringstream, поэтому имеет место существенная просадка по производительности по сравнению с другими типами.
В зависимости от значения параметра R сериализация возможна в формате с фиксированной или плавающей точкой. При десериализации формат не важен.
typedef ::wjson::value<long double>::serializer serializer_t;
typedef ::wjson::value<long double, 4 >::serializer serializer4_t;
long double value = 0.00000001234501;
std::cout << value << std::endl;
std::string json;
serializer_t()(value, std::back_inserter(json));
std::cout << json << std::endl;
serializer_t()(value, json.begin(), json.end(), 0 );
std::cout << value << std::endl;
value=-1;
serializer4_t()(value, json.begin(), json.end(), 0 );
std::cout << value << std::endl;
std::cout << std::endl;
value=12345.12345;
json.clear();
serializer4_t()(value, std::back_inserter(json));
std::cout << json << std::endl;
value=-1;
serializer4_t()(value, json.begin(), json.end(), 0 );
std::cout << value << std::endl;
value=-1;
serializer_t()(value, json.begin(), json.end(), 0 );
std::cout << value << std::endl;Вывод:
1.2345e-08
1.234501e-08
1.2345e-08
1.2345e-08
12345.1234
12345.1
12345.1
В качестве контейнера строк, помимо std::string, могут использоваться std::vector<char> и одномерные массивы типа char, например char str[128]. Указатели типа char * не поддерживаются. Для std::string и std::vector<char> можно задавать размер резервируемой памяти (по умолчанию 64).
Обратите внимание на то, что десериализатор строк преобразует hex-коды вида \uXXXX в utf-8 символы (за исключением ASCII непечатных символов), а сериализует без преобразования (за исключением непечатных ASCII символов). На это стоит обратить внимание, т.к. некоторые сторонние десериализаторы понимают utf-8, но при сериализации символы utf-8, не входящие в ASCII диапазон преобразуют, в hex-коды.
Не utf-8 байты сериализуются/десериализуются как \xXX. Для передачи бинарных данных лучше предварительно преобразовать в base64 - это более компактно.