PIJSON improvements and doc reference

This commit is contained in:
2022-09-28 18:08:19 +03:00
parent 2d2f6b254b
commit 44876836c5
3 changed files with 241 additions and 47 deletions

View File

@@ -26,7 +26,67 @@
//! \~english //! \~english
//! //!
//! \~russian //! \~russian
//! JSON - это древовидная структура, каждый элемент которой может бить либо
//! парой имя:значение, либо массивом, либо объектом, т.е. именованным
//! списком элементов. Корневой элемент JSON может быть либо массивом,
//! либо объектом.
//! //!
//! Массивы заключены в квадратные скобки [], их элементы не имеют имени
//! и разделяются запятыми.
//!
//! Объекты заключены в фигурные скобки {}, их элементы имеют имя
//! и разделяются запятыми.
//!
//!
//! \~english \section PIJSON_sec1 PIJSON tree
//! \~russian \section PIJSON_sec1 Дерево PIJSON
//! \~english
//!
//! \~russian
//! %PIJSON представляет собой элемент дерева JSON. Каждый элемент имеет тип (\a type())
//! и может иметь имя (\a name()). Если это конечный элемент,то он будет иметь значение,
//! доступное через \a value(), \a toBool(), \a toInt(), \a toDouble() или \a toString().
//!
//! Если элемент преставляет собой массив, то его размер доступен через \a size(),
//! а элементы массива через целочисленный оператор []. Весь массив доступен через \a array().
//!
//! Если элемент преставляет собой объект, то его размер доступен через \a size(),
//! а элементы объекта через строковый оператор []. Проверить наличие элемента по имени можно
//! с помощью \a contains(). Весь объект доступен через \a object().
//!
//! Создать дерево из текстового представления JSON можно с помощью \a fromJSON(), а
//! преобразовать в текст с помощью \a toJSON().
//!
//!
//! \~english \section PIJSON_sec2 PIJSON creation
//! \~russian \section PIJSON_sec2 Создание PIJSON
//! \~english
//!
//! \~russian
//! Для создания нового дерева необходимо лишь создать пустой корневой PIJSON и заполнить его
//! значениями, массивами или объектами с помощью целочисленного или строкового оператора [].
//! В зависимости от типа аргумента элемент преобразуется либо в массив, либо в объект.
//!
//! При приравнивании PIJSON к какому-либо значению, его тип автоматически установится в нужный.
//! При обращении на запись целочисленным оператором [] размер массива автоматически увеличится
//! при необходимости.
//!
//!
//! \~english \section PIJSON_sec3 Mask/unmask
//! \~russian \section PIJSON_sec3 Маскирование/размаскирование
//! \~english
//!
//! \~russian
//! Строковые значения в стандарте JSON могут иметь в явном виде только печатные символы,
//! спецсимволы и юникод должны быть преобразованы маскированием, т.е., например, вместо
//! символа новой строки должно быть "\n", а не-ASCII символы должны быть в виде "\uXXXX".
//!
//! Оператор вывода в PICout не выполняет маскирования строк.
//!
//! Методы \a toJSON() и \a fromJSON() маскируют и размаскируют строковые поля.
//!
//!
PIJSON PIJSON::newObject() { PIJSON PIJSON::newObject() {
@@ -43,6 +103,38 @@ PIJSON PIJSON::newArray() {
} }
PIJSON PIJSON::newString(const PIString & v) {
PIJSON ret;
ret = v;
return ret;
}
const PIVector<PIJSON> & PIJSON::array() const {
if (!isArray())
return nullEntry().c_array;
return c_array;
}
const PIMap<PIString, PIJSON> & PIJSON::object() const {
if (!isObject())
return nullEntry().c_object;
return c_object;
}
//! \details
//! \~english
//! If "v" type is boolean set type to \a PIJSON::Boolean.\n
//! If "v" type is any numeric set type to \a PIJSON::Number.\n
//! If "v" type is string set type to \a PIJSON::String.\n
//! In case of any other types set element type to \a PIJSON::Invalid.
//! \~russian
//! Если тип "v" логический, то устанавливает тип в \a PIJSON::Boolean.\n
//! Если тип "v" любой численный, то устанавливает тип в \a PIJSON::Number.\n
//! Если тип "v" строковый, то устанавливает тип в \a PIJSON::String.\n
//! Если тип "v" любой другой, то устанавливает тип в \a PIJSON::Invalid.
void PIJSON::setValue(const PIVariant & v) { void PIJSON::setValue(const PIVariant & v) {
c_value = v; c_value = v;
switch (v.type()) { switch (v.type()) {
@@ -73,9 +165,11 @@ void PIJSON::clear() {
int PIJSON::size() const { int PIJSON::size() const {
if (!isArray()) if (isArray())
return 0;
return c_array.size_s(); return c_array.size_s();
if (isObject())
return c_object.size_s();
return 0;
} }
@@ -86,8 +180,8 @@ bool PIJSON::contains(const PIString & key) const {
void PIJSON::resize(int new_size) { void PIJSON::resize(int new_size) {
c_array.resize(new_size);
c_type = Array; c_type = Array;
c_array.resize(new_size, newString());
} }
@@ -100,6 +194,8 @@ const PIJSON & PIJSON::operator[](int index) const {
PIJSON & PIJSON::operator[](int index) { PIJSON & PIJSON::operator[](int index) {
c_type = Array; c_type = Array;
if (index >= c_array.size_s())
c_array.resize(index + 1, newString());
PIJSON & ret(c_array[index]); PIJSON & ret(c_array[index]);
return ret; return ret;
} }
@@ -131,9 +227,9 @@ PIJSON & PIJSON::operator[](const PIString & key) {
} }
PIString PIJSON::toJSON() const { PIString PIJSON::toJSON(PrintType print_type) const {
PIString ret; PIString ret;
print(ret, *this, "", true); print(ret, *this, "", print_type == Tree, true);
return ret; return ret;
} }
@@ -294,8 +390,8 @@ PIString PIJSON::stringUnmask(const PIString & s) {
} }
void PIJSON::print(PIString & s, const PIJSON & v, PIString tab, bool transform, bool comma) { void PIJSON::print(PIString & s, const PIJSON & v, PIString tab, bool spaces, bool transform, bool comma) {
s += tab; if (spaces) s += tab;
/* /*
switch (v.c_type) { switch (v.c_type) {
case JSONEntry::Invalid: s << "(Invalid)"; break; case JSONEntry::Invalid: s << "(Invalid)"; break;
@@ -307,7 +403,10 @@ void PIJSON::print(PIString & s, const PIJSON & v, PIString tab, bool transform,
case JSONEntry::Array: s << "(Array)"; break; case JSONEntry::Array: s << "(Array)"; break;
} }
*/ */
if (v.name().isNotEmpty()) s += '"' + (transform ? stringMask(v.name()) : v.name()) + "\": "; if (v.name().isNotEmpty()) {
s += '"' + (transform ? stringMask(v.name()) : v.name()) + "\":";
if (spaces) s += ' ';
}
switch (v.c_type) { switch (v.c_type) {
case PIJSON::Invalid: break; case PIJSON::Invalid: break;
case PIJSON::Null: s += "null"; break; case PIJSON::Null: s += "null"; break;
@@ -315,26 +414,30 @@ void PIJSON::print(PIString & s, const PIJSON & v, PIString tab, bool transform,
case PIJSON::Number: s += v.c_value.toString(); break; case PIJSON::Number: s += v.c_value.toString(); break;
case PIJSON::String: s += '"' + (transform ? stringMask(v.c_value.toString()) : v.c_value.toString()) + '"'; break; case PIJSON::String: s += '"' + (transform ? stringMask(v.c_value.toString()) : v.c_value.toString()) + '"'; break;
case PIJSON::Object: case PIJSON::Object:
s += "{\n"; s += "{";
if (spaces) s += '\n';
{ {
PIString ntab = tab + " "; PIString ntab = tab + " ";
auto it = v.c_object.makeIterator(); auto it = v.c_object.makeIterator();
int cnt = 0; int cnt = 0;
while (it.next()) while (it.next())
print(s, it.value(), ntab, transform, ++cnt < v.c_object.size_s()); print(s, it.value(), ntab, spaces, transform, ++cnt < v.c_object.size_s());
} }
s += tab + "}"; if (spaces) s += tab;
s += "}";
break; break;
case PIJSON::Array: case PIJSON::Array:
s += "[\n"; s += "[";
if (spaces) s += '\n';
{ {
PIString ntab = tab + " "; PIString ntab = tab + " ";
for (int i = 0; i < v.c_array.size_s(); ++i) for (int i = 0; i < v.c_array.size_s(); ++i)
print(s, v.c_array[i], ntab, transform, i < v.c_array.size_s() - 1); print(s, v.c_array[i], ntab, spaces, transform, i < v.c_array.size_s() - 1);
} }
s += tab + "]"; if (spaces) s += tab;
s += "]";
break; break;
} }
if (comma) s += ','; if (comma) s += ',';
s += "\n"; if (spaces) s += "\n";
} }

View File

@@ -36,56 +36,145 @@
class PIP_EXPORT PIJSON { class PIP_EXPORT PIJSON {
friend PICout operator <<(PICout s, const PIJSON & v); friend PICout operator <<(PICout s, const PIJSON & v);
public: public:
//! \~english
//! Type of JSON tree element
//! \~russian
//! Тип элемента дерева JSON
enum Type { enum Type {
Invalid, Invalid /*! \~english Invalid type \~russian Недействительный тип */,
Null, Null /*! \~english Without value, null \~russian Без значения, null */,
Boolean, Boolean /*! \~english Boolean, /b true or /b false \~russian Логическое, /b true или /b false */,
Number, Number /*! \~english Integer or floating-point number \~russian Целое либо число с плавающей точкой */,
String, String /*! \~english Text \~russian Текст */,
Object, Object /*! \~english Object, {} \~russian Объект, {} */,
Array Array /*! \~english Array, [] \~russian Массив, [] */
}; };
//! \~english
//! Generate JSON variant
//! \~russian
//! Вариант генерации JSON
enum PrintType { enum PrintType {
Compact, Compact /*! \~english Without spaces, minimum size \~russian Без пробелов, минимальный размер */,
Tree Tree /*! \~english With spaces and new-lines, human-readable \~russian С пробелами и новыми строками, читаемый человеком */
}; };
//! \~english Contructs invalid %PIJSON.
//! \~russian Создает недействительный %PIJSON.
PIJSON() {} PIJSON() {}
PIJSON(const PIJSON & o) = default; PIJSON(const PIJSON & o) = default;
static PIJSON newObject(); //! \~english Returns name of element, or empty string if it doesn`t have name.
static PIJSON newArray(); //! \~russian Возвращает имя элемента, либо пустую строку, если имени нет.
const PIString & name() const {return c_name;} const PIString & name() const {return c_name;}
const PIVector<PIJSON> & array() const {return c_array;}
const PIMap<PIString, PIJSON> & object() const {return c_object;} //! \~english Returns elements array of this element, or empty array if element is not \a PIJSON::Array.
//! \~russian Возвращает массив элементов этого элемента, либо пустой массив, если тип элемента не \a PIJSON::Array.
const PIVector<PIJSON> & array() const;
//! \~english Returns elements map of this element, or empty map if element is not \a PIJSON::Object.
//! \~russian Возвращает словарь элементов этого элемента, либо пустой словарь, если тип элемента не \a PIJSON::Object.
const PIMap<PIString, PIJSON> & object() const;
//! \~english Returns element value.
//! \~russian Возвращает значение элемента.
const PIVariant & value() const {return c_value;} const PIVariant & value() const {return c_value;}
//! \~english Returns element value as bool.
//! \~russian Возвращает значение элемента как логическое.
bool toBool() const {return c_value.toBool();} bool toBool() const {return c_value.toBool();}
//! \~english Returns element value as integer number.
//! \~russian Возвращает значение элемента как целое число.
int toInt() const {return c_value.toInt();} int toInt() const {return c_value.toInt();}
//! \~english Returns element value as floating-point number.
//! \~russian Возвращает значение элемента как число с плавающей точкой.
double toDouble() const {return c_value.toDouble();} double toDouble() const {return c_value.toDouble();}
//! \~english Returns element value as string, valid for all types.
//! \~russian Возвращает значение элемента как строка, действительно для всех типов.
PIString toString() const {return c_value.toString();} PIString toString() const {return c_value.toString();}
//! \~english Returns element type.
//! \~russian Возвращает тип элемента.
Type type() const {return c_type;} Type type() const {return c_type;}
//! \~english Returns if element is valid.
//! \~russian Возвращает действителен ли элемент.
bool isValid() const {return c_type != Invalid;} bool isValid() const {return c_type != Invalid;}
//! \~english Returns if element is \a PIJSON::Object.
//! \~russian Возвращает является ли элемент \a PIJSON::Object.
bool isObject() const {return c_type == Object;} bool isObject() const {return c_type == Object;}
//! \~english Returns if element is \a PIJSON::Array.
//! \~russian Возвращает является ли элемент \a PIJSON::Array.
bool isArray() const {return c_type == Array;} bool isArray() const {return c_type == Array;}
//! \~english Set value and type of element from "v".
//! \~russian Устанавливает значение и тип элемента из "v".
void setValue(const PIVariant & v); void setValue(const PIVariant & v);
//! \~english Clear element and set it to \a PIJSON::Invalid.
//! \~russian Очищает элемент и устанавливает его в \a PIJSON::Invalid.
void clear(); void clear();
//! \~english Returns size of elements array if type is \a PIJSON::Array, size of elements map if type is \a PIJSON::Object, otherwise returns 0.
//! \~russian Возвращает размер массива элементов если тип \a PIJSON::Array, размер словаря элементов если тип \a PIJSON::Object, иначе возвращает 0.
int size() const; int size() const;
//! \~english Returns if elements map contains key "key" if type is \a PIJSON::Object, otherwise returns \b false.
//! \~russian Возвращает содержит ли словарь элементов ключ "key" если тип \a PIJSON::Object, иначе возвращает \b false.
bool contains(const PIString & key) const; bool contains(const PIString & key) const;
//! \~english Set element type to \a PIJSON::Array and resize elements array to "new_size".
//! \~russian Устанавливает тип элемента в \a PIJSON::Array и изменяет размер массива элементов на "new_size".
void resize(int new_size); void resize(int new_size);
const PIJSON & operator[](int index) const;
PIJSON & operator[](int index); //! \~english Synonim of \a setValue().
//! \~russian Аналог \a setValue().
PIJSON & operator=(const PIVariant & v) {setValue(v); return *this;} PIJSON & operator=(const PIVariant & v) {setValue(v); return *this;}
PIJSON & operator=(const PIJSON & v); PIJSON & operator=(const PIJSON & v);
//! \~english Returns element from array with index "index" if type is \a PIJSON::Array, otherwise returns invalid %PIJSON.
//! \~russian Возвращает элемент из массива по индексу "index" если тип \a PIJSON::Array, иначе возвращает недействительный %PIJSON.
const PIJSON & operator[](int index) const;
//! \~english Set element type to \a PIJSON::Array, resize if necessary and returns element from array with index "index".
//! \~russian Устанавливает тип элемента в \a PIJSON::Array, изменяет размер массива при неоходимости и возвращает элемент из массива по индексу "index".
PIJSON & operator[](int index);
//! \~english Returns element from map with key "key" if type is \a PIJSON::Object, otherwise returns invalid %PIJSON.
//! \~russian Возвращает элемент из словаря по ключу "key" если тип \a PIJSON::Object, иначе возвращает недействительный %PIJSON.
PIJSON operator[](const PIString & key) const; PIJSON operator[](const PIString & key) const;
//! \~english Set element type to \a PIJSON::Object and returns element from map with key "key". If element with this key doesn`t exists, it will be created.
//! \~russian Устанавливает тип элемента в \a PIJSON::Object и возвращает элемент из словаря по ключу "key". Если элемента с таким ключом не существует, он будет создан.
PIJSON & operator[](const PIString & key); PIJSON & operator[](const PIString & key);
PIJSON operator[](const char * key) const {return (*this)[PIString::fromUTF8(key)];} PIJSON operator[](const char * key) const {return (*this)[PIString::fromUTF8(key)];}
PIJSON & operator[](const char * key) {return (*this)[PIString::fromUTF8(key)];} PIJSON & operator[](const char * key) {return (*this)[PIString::fromUTF8(key)];}
PIString toJSON() const;
//! \~english Returns text representation of JSON tree.
//! \~russian Возвращает текстовое представление дерева JSON.
PIString toJSON(PrintType print_type = Tree) const;
//! \~english Parse text representation of JSON "str" and returns it root element.
//! \~russian Разбирает текстовое представление JSON "str" и возвращает его корневой элемент.
static PIJSON fromJSON(PIString str); static PIJSON fromJSON(PIString str);
static PIJSON newObject();
static PIJSON newArray();
static PIJSON newString(const PIString & v = PIString());
private: private:
static PIJSON & nullEntry(); static PIJSON & nullEntry();
static PIString parseName(PIString & s); static PIString parseName(PIString & s);
@@ -94,7 +183,7 @@ private:
static PIJSON parseArray(PIString s); static PIJSON parseArray(PIString s);
static PIString stringMask(const PIString & s);; static PIString stringMask(const PIString & s);;
static PIString stringUnmask(const PIString & s);; static PIString stringUnmask(const PIString & s);;
static void print(PIString & s, const PIJSON & v, PIString tab, bool transform = false, bool comma = false); static void print(PIString & s, const PIJSON & v, PIString tab, bool spaces, bool transform = false, bool comma = false);
PIString c_name; PIString c_name;
PIVariant c_value; PIVariant c_value;
@@ -112,7 +201,7 @@ inline PICout operator <<(PICout s, const PIJSON & v) {
s.space(); s.space();
s.saveAndSetControls(0); s.saveAndSetControls(0);
PIString str; PIString str;
PIJSON::print(str, v, ""); PIJSON::print(str, v, "", true);
s << str; s << str;
s.restoreControls(); s.restoreControls();
return s; return s;

View File

@@ -35,8 +35,8 @@ int main(int argc, char * argv[]) {
s = PIString::fromUTF8("{\"st\\u0426r\":\"\\\\ \\\" \\u0425\\u0430\\n\"}"); s = PIString::fromUTF8("{\"st\\u0426r\":\"\\\\ \\\" \\u0425\\u0430\\n\"}");
//s = PIString::fromUTF8("{\"str\":\"Ха\"}"); //s = PIString::fromUTF8("{\"str\":\"Ха\"}");
PIJSON json = PIJSON::fromJSON(s); PIJSON json = PIJSON::fromJSON(s);
piCout << json; //piCout << json;
piCout << json.toJSON(); //piCout << json.toJSON();
//json.resize(3); //json.resize(3);
//json["0"].setValue(123); //json["0"].setValue(123);
//json["1"].setValue("sec"); //json["1"].setValue("sec");
@@ -44,19 +44,21 @@ int main(int argc, char * argv[]) {
//json["2"]["s"].setValue(-1);*/ //json["2"]["s"].setValue(-1);*/
//json[0]["Passport"]["id"] = 0xFF; //json[0]["Passport"]["id"] = 0xFF;
//piCout << json; //piCout << json;
json = PIJSON::newObject(); json = PIJSON();
json["num"] = 123; json[0] = 123;
json["str__"] = PIString::fromUTF8("string русский ℃ 😆 "); json[1] = PIString::fromUTF8("string русский хаха !");
json["obj"]["b"] = true; json[2]["b"] = true;
json["obj"]["i"] = -1; json[2]["i"] = -1;
auto & arr(json["obj"]["arr"]); auto & arr(json[3]);
arr.resize(3);
arr[0] = 10; arr[0] = 10;
arr[1] = 11.2E-1; arr[1] = 11.2E-1;
arr[2] = "!!!"; arr[2] = "!!!";
json["obj2"] = json["obj"]; json[5] = json[2];
json[7] = false;
//piCout << json; //piCout << json;
piCout << json.toJSON(); piCout << json;
piCout << json["str__"].toString().toUTF8(); piCout << json.toJSON(PIJSON::Tree);
piCout << json.toJSON(PIJSON::Compact);
//piCout << json["str__"].toString().toUTF8();
return 0; return 0;
} }