Skip to content

SimpleJson

Владимир Мигашко edited this page Sep 5, 2016 · 13 revisions

<< Назад

Для описания сериализации простых типов используется конструкция 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 - это более компактно.

<< Назад

Clone this wiki locally