diff --git a/sources/classes/JsonReWriter.md b/sources/classes/JsonReWriter.md
new file mode 100644
index 0000000..0263fa8
--- /dev/null
+++ b/sources/classes/JsonReWriter.md
@@ -0,0 +1,710 @@
+# Описание класса JsonReWriter
+
+## Информация о версии
+
+Версия класса: 1.0
+
+Впервые введено в пакет с версии: 1.1.0
+
+Описание класса: Класс для работы с JSON-файлами.
+
+## Публичные свойства и константы класса
+
+В классе определены следующие свойства:
+
+- `string $JsonString` - строка JSON (чтение/запись).
+
+## Быстрый старт
+
+### Правила формирования ключей.
+
+Ключ для чтения/записи данных класса формируется следующим образом: `ключ/подключ/подключ подключа` .
+
+Например, если дан json-файл:
+
+ {
+ "test": {
+ "subtest": {
+ "AAA": "123",
+ "BBB": 1.23
+ }
+ },
+ "test1": {
+ "test": 123
+ },
+ "test2": {
+ "test": true
+ },
+ "test3": {
+ "test": {
+ "res": "[1,2,3]"
+ }
+ }
+ }
+
+Пусть требуется получить значение `BBB`, тогда ключ должен быть `test/subtest/BBB`.
+
+### Чтение.
+
+1. Создайте элемент класса `$json = new JsonReWriter ();`
+2. Если у вас требуется загрузить json из файла `$fileName`, то воспользуйтесь методом `LoadFromFile`:
+ `$json->LoadFromFile($fileName);`, если же json представлен строкой `$jsonStr`, то загрузите её в свойство
+ `$JsonString`: `$json->JsonString = $jsonStr;`
+3. Далее можно пользоваться любым методом для чтения `Read*`, в том числе и общим `$json->Read(...)`.
+
+**Пример:**
+
+ // Имя файла
+ $fileName = __DIR__ . "/test.json";
+ // Создаю класс
+ $json = new JsonReWriter();
+ // Загшружаю данные из файла
+ $json->LoadFromFile($fileName);
+ // Получаю число
+ $float = $json->ReadFloat("test/subtest/BBB", 0.2);
+
+В итоге в `$float` будет `1.23`.
+
+### Запись.
+
+1. Создайте элемент класса `$json = new JsonReWriter ();`
+2. Далее можно пользоваться любым методом для записи `Write*`, в том числе и общим `$json->Write(...)`.
+3. Если вам требуется создать json файл с именем `$fileName`, то воспользуйтесь методом `SaveToFile`:
+ `$json->SaveToFile($fileName);`, если же json должен быть представлен строкой `$jsonStr`, то загрузите её из свойства
+ `$JsonString`: `$jsonStr = $json->JsonString;`
+
+**Пример:**
+
+ // Имя файла
+ $fileName = __DIR__ . "/test.json";
+ // Создаю класс
+ $json = new JsonReWriter();
+ // Загшружаю данные из файла
+ $json->LoadFromFile($fileName);
+ // Получаю число
+ try {
+ $json->Write("test/subtest/BBB", 0.2);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+В итоге в `test/subtest/BBB` вместо `1.23` будет `0.2`.
+
+## Коды ошибок JsonErrorCode
+
+Ниже представлена таблица основных кодов ошибки:
+
+| Ошибка | Описание | Введено с версии |
+|:-------------------:|:---------------------------------------------------------------------------:|:----------------:|
+| Unknown | Неизвестная ошибка | 1.0 |
+| None | Ошибок нет | 1.0 |
+| Depth | Достигнута максимальная глубина стека | 1.0 |
+| StateMismatch | Неверный или некорректный JSON | 1.0 |
+| CTRLChar | Ошибка управляющего символа, возможно, неверная кодировка | 1.0 |
+| Syntax | Синтаксическая ошибка | 1.0 |
+| UTF8 | Некорректные для кодировки UTF-8 символы, возможно, неверная кодировка | 1.0 |
+| Recursion | Одна или несколько зацикленных ссылок в кодируемом значении | 1.0 |
+| InfOrNan | Одно или несколько значений NAN или INF в кодируемом значении | 1.0 |
+| UnsupportedType | Передали значение с неподдерживаемым типом | 1.0 |
+| InvalidPropertyName | Имя свойства не может быть закодировано | 1.0 |
+| UTF16 | Некорректный для кодировки UTF-16 символ, возможно, некорректно закодирован | 1.0 |
+| KeyIsNotArray | Ключ не содержит вложений, хотя от него требуется обратное | 1.0 |
+| NotISerializable | Класс не реализует интерфейс ISerializable | 1.0 |
+
+### Методы и функции перечисления JsonErrorCode
+
+Перечисление содержит **статический метод** `static function FromLastError (): JsonErrorCode`, который получает код
+ошибки из последней JSON ошибки.
+
+Например, при успешной загрузке, можем проверить ошибки:
+
+ $errors = JsonErrorCode::FromLastError ();
+
+После того, как мы выведем `$errors`, мы получим `JsonErrorCode::None`.
+
+## Исключение JsonException
+
+Исключение расширяет класс `Exception`, поэтому может выбрасываться через `throw`.
+
+### Свойства
+
+Исключение содержит следующие свойства:
+
+- `?string $JsonString` - строка JSON (или null);
+- `JsonErrorCode $ErrorCode` - код ошибки JSON;
+- `?string $ErrorMessage` - сообщение об ошибке JSON (в отличие от функции json_last_error_msg(), данная переменная при
+ отсутствии ошибок выводит null, а не "No error").
+
+### Методы и функции
+
+#### Конструктор.
+
+Конструктор принимает **3 необязательных параметра**:
+
+* `?string $json` - строка JSON (по умолчанию, `null`);
+* `JsonErrorCode $errorCode` - код ошибки (по умолчанию, `JsonErrorCode::Unknown`);
+* `?string $errorMessage` - сообщение об ошибке (по умолчанию, `null`).
+
+В результате создаётся новое исключение `JsonException`.
+
+Пример:
+
+ throw new JsonException("{}", JsonErrorCode::Depth, "Пример");
+
+Создаст исключение `JsonException`.
+
+## Методы и функции
+
+### Конструктор и деструктор.
+
+Конструктор не принимает никаких параметров.
+
+В результате создаётся новый класс `JsonReWriter`.
+
+**Пример:**
+
+ // Контсуктор
+ $json = new JsonReWriter ();
+ // Деструктор
+ unset($json);
+
+Создаст и уничтожит класс `JsonReWriter`.
+
+### Сохранение и загрузка из файла.
+
+За сохранение и загрузку отвечают 2 метода: `SaveToFile` и `LoadFromFile`.
+
+#### Сохранение в файл (метод `SaveToFile`)
+
+Этот метод сохраняет содержимое JSON в файл. Он содержит **1 обязательный параметр**:
+
+* `string $fileName` - имя файла на диске.
+
+Метод возвращает `bool` - сохранены ли данные в файл: `true` - да, `false` - нет.
+
+Синтаксис:
+
+ public function SaveToFile (string $fileName): bool
+
+**Пример:**
+
+ // Имя файла
+ $fileName = __DIR__ . "/test.json";
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Сохраняем созданный JSON файл
+ $json->SaveToFile($fileName);
+
+Содержимое файла `test.json` представлено далее:
+
+ {
+ "test": {
+ "subtest": {
+ "AAA": "123",
+ "BBB": 1.23
+ }
+ },
+ "test1": {
+ "test": 123
+ },
+ "test2": {
+ "test": true
+ },
+ "test3": {
+ "test": {
+ "res": "[1,2,3]"
+ }
+ }
+ }
+
+#### Загрузка файла (метод `LoadFromFile`)
+
+Этот метод загружает содержимое файла в класс. Он содержит **1 обязательный параметр**:
+
+* `string $fileName` - имя файла на диске.
+
+Метод возвращает `bool` - загружены ли данные из файла: `true` - да, `false` - нет.
+
+Синтаксис:
+
+ public function LoadFromFile (string $fileName): bool
+
+**Пример:**
+Пусть дан файл `test.json`, содержимое которого представлено далее:
+
+ {
+ "test": {
+ "subtest": {
+ "AAA": "123",
+ "BBB": 1.23
+ }
+ },
+ "test1": {
+ "test": 123
+ },
+ "test2": {
+ "test": true
+ },
+ "test3": {
+ "test": {
+ "res": "[1,2,3]"
+ }
+ }
+ }
+
+Следующий код загрузит это содержимое в класс:
+
+ // Имя файла
+ $fileName = __DIR__ . "/test.json";
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Загружаю данные
+ $json->LoadFromFile($fileName);
+
+### Чтение данных
+
+Для чтения данных используется один общий метод `Read` и 7 его производных метода: `ReadString`, `ReadInt`, `ReadFloat`,
+`ReadBool`, `ReadArray`, `ReadObject` и `ReadSerializable`.
+
+#### Метод `Read`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `mixed $default` (значение по умолчанию, задан по умолчанию в `null`).
+
+Этот метод возвращает `mixed`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function Read (string $key, mixed $default = null): mixed
+
+**Пример,**
+
+ // Создаю класс
+ $json = new JsonReWriter();
+ // Заполняю данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->Write("test3/test/res", json_encode([1, 2, 3]));
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ // Получаю значение
+ $float = (float)$json->Read("test/subtest/BBB"));
+
+В результате, переменная `$float` будет иметь значение `1.23`.
+
+#### Метод `ReadString`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `string $default` (значение по умолчанию, задан по умолчанию в `""`).
+
+Этот метод возвращает `string`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadString (string $key, string $default = ""): string
+
+#### Метод `ReadInt`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `int $default` (значение по умолчанию, задан по умолчанию в `0`).
+
+Этот метод возвращает `int`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadInt (string $key, int $default = 0): int
+
+#### Метод `ReadFloat`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `float $default` (значение по умолчанию, задан по умолчанию в `0.0`).
+
+Этот метод возвращает `float`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadFloat (string $key, float $default = 0.0): float
+
+#### Метод `ReadBool`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `bool $default` (значение по умолчанию, задан по умолчанию в `false`).
+
+Этот метод возвращает `bool`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadBool (string $key, bool $default = false): bool
+
+#### Метод `ReadArray`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `array $default` (значение по умолчанию, задан по умолчанию в `[]`).
+
+Этот метод возвращает `array`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadArray (string $key, array $default = []): array
+
+#### Метод `ReadObject`
+
+Это метод, который читает значение ключа JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `object $default` (значение по умолчанию).
+
+Этот метод возвращает `object`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadObject (string $key, object $default): object
+
+#### Метод `ReadSerializable`
+
+Это метод, который читает значение ключа JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `string $serializableClassName` (имя класса, реализующего интерфейс ISerializable, с namespace).
+
+Этот метод возвращает класс, реализующий интерфейс `ISerializable`.
+
+**Важно!** Этот метод может выбросить исключение `JsonException`, если класс, заданный в `$serializableClassName` не
+реализует интерфейс `ISerializable`.
+
+Синтаксис:
+
+ public function ReadSerializable (string $key, string $serializableClassName): ISerializable
+
+**Пример,**
+
+Пусть для примера, класс `Demo` из namespace `iam\namespace` реализует интерфейс `ISerializable`.
+
+ // Создаю класс
+ $json = new JsonReWriter();
+ // ... Здесь где-то загрузка данных
+ // Получаю класс
+ try {
+ /**
+ * @var Demo $unSerializableClass
+ */
+ $unSerializableClass = $json->ReadSerializable("test", "iam\\namespace\\Demo");
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+В результате, переменная `$unSerializableClass` будет содержать данные класса `Demo`.
+
+### Запись данных
+
+Для чтения данных используется один общий метод `Write` и 3 его производных метода: `WriteArray`, `WriteObject` и
+`WriteSerializable`.
+
+**Важно!** Лобой из вышеуказанных методов может выбросить исключение `JsonException`, если ключ не содержит вложений,
+хотя от него требуется обратное.
+
+#### Метод `Write`
+
+Это метод, который записывает значение в ключ JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `mixed $value` (записываемое значение).
+
+Этот метод ничего не возвращает.
+
+Синтаксис:
+
+ public function Write (string $key, mixed $value): void
+
+**Пример,**
+
+ // Имя файла
+ $fileName = __DIR__ . "/test.json";
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Сохраняем созданный JSON файл
+ $json->SaveToFile($fileName);
+
+Содержимое файла `test.json` представлено далее:
+
+ {
+ "test": {
+ "subtest": {
+ "AAA": "123",
+ "BBB": 1.23
+ }
+ },
+ "test1": {
+ "test": 123
+ },
+ "test2": {
+ "test": true
+ },
+ "test3": {
+ "test": {
+ "res": "[1,2,3]"
+ }
+ }
+ }
+
+#### Метод `WriteArray`
+
+Это метод, который записывает значение в ключ JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `array $array` (записываемое значение).
+
+Этот метод ничего не возвращает.
+
+Синтаксис:
+
+ public function WriteArray (string $key, array $array): void
+
+#### Метод `WriteObject`
+
+Это метод, который записывает значение в ключ JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `object $value` (записываемое значение).
+
+Этот метод ничего не возвращает.
+
+Синтаксис:
+
+ public function WriteObject (string $key, object $value): void
+
+#### Метод `WriteSerializable`
+
+Это метод, который записывает значение в ключ JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `ISerializable $serializableValue` (записываемое значение).
+
+Этот метод ничего не возвращает.
+
+Синтаксис:
+
+ public function WriteSerializable (string $key, ISerializable $serializableValue): void
+
+**Пример,**
+Пусть для примера, класс `Demo` из namespace `iam\namespace` реализует интерфейс `ISerializable`.
+
+ // Имя файла
+ $fileName = __DIR__ . "/test.json";
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Создаём класс Demo
+ $serializableClass = new Demo(...);
+ // Заполним данными
+ try {
+ $json->WriteSerializable("test", $serializableClass);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ ...
+
+### Работа с ключами JSON
+
+Для работы с ключами JSON есть 2 метода: `IsKeyExists` и `GetKeys`.
+
+#### Метод `IsKeyExists`
+
+Это метод проверяем наличие ключа в JSON. Он имеет **1 обязательный параметр** - `string $key` (ключ).
+
+Этот метод возвращает `bool`: `true` если ключ найден и `false` в противном случае.
+
+Синтаксис:
+
+ public function IsKeyExists (string $key): bool
+
+**Пример,**
+
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Проверяем ключи
+ $check1 = $json->IsKeyExists("test/subtest/AAA");
+ $check2 = $json->IsKeyExists("test/subtest/ССС");
+
+В результате, `$check1` будет `true`, а `$check2` - `false`.
+
+#### Метод `GetKeys`
+
+Это метод получает список ключей. Он имеет **2 необязательных параметра**:
+
+- `string $parentKey` (ключ родителя (или "" (установлено по умолчанию) для всех);
+- `bool $includeChildren` (нужно ли включать дочерние ключи (по умолчанию, да)).
+
+Этот метод возвращает `array`: список ключей.
+
+Синтаксис:
+
+ public function GetKeys (string $parentKey = "", bool $includeChildren = true): array
+
+**Пример,**
+
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Получаем ключи
+ $keys1 = $json->GetKeys("test");
+ $keys2 = $json->GetKeys("test", false);
+ $keys3 = $json->GetKeys();
+
+В результате, `$key1` будет следующим массивом:
+
+ [
+ "test/subtest",
+ "test/subtest/AAA",
+ "test/subtest/BBB"
+ ]
+
+`$key2` будет следующим массивом:
+
+ [
+ "subtest"
+ ]
+
+`$key3` будет следующим массивом:
+
+ [
+ "test",
+ "test/subtest",
+ "test/subtest/AAA",
+ "test/subtest/BBB",
+ "test1",
+ "test1/test",
+ "test2",
+ "test2/test",
+ "test3",
+ "test3/test",
+ "test3/test/res"
+ ]
+
+### Удаление ключей JSON
+
+Для удаления ключей JSON есть 2 метода: `DeleteKey`, который удаляет только определённый ключ и `Clear`, который удаляет
+**все ключи** из json-файла.
+
+#### Метод `DeleteKey`
+
+Это метод удаляет только определённый ключ в JSON. Он имеет **1 обязательный параметр** - `string $key` (ключ).
+
+Этот метод возвращает `bool` - результат удаления ключа: `true` - удаление прошло успешно, `false` - произошла ошибка
+при удалении.
+
+Синтаксис:
+
+ public function DeleteKey (string $key): bool
+
+**Пример,**
+
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Получаемем ключи до удаления
+ $check1 = $json->GetKeys("test/subtest");
+ // Удаляем ключ
+ $this->DeleteKey("test/subtest/BBB");
+ // Получаемем ключи после удаления
+ $check2 = $json->GetKeys("test/subtest");
+
+В результате, `$check1` будет
+
+ [
+ "test/subtest",
+ "test/subtest/AAA",
+ "test/subtest/BBB"
+ ]
+
+а `$check2`:
+
+ [
+ "test/subtest",
+ "test/subtest/AAA"
+ ]
+
+#### Метод `Clear`
+
+Это метод удаляет **все ключи** из json-файла. Он не имеет никаких параметров и ничего не возвращает.
+
+Синтаксис:
+
+ public function Clear (): void
+
+**Пример,**
+
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Очищаем
+ $json->Clear();
+ // Получаем ключи
+ $keys = $json->GetKeys();
+
+В результате, `$key` будет следующим массивом:
+
+ [
+ ]
\ No newline at end of file
diff --git a/sources/classes/JsonReWriter.php b/sources/classes/JsonReWriter.php
index 49e7011..50e1d53 100644
--- a/sources/classes/JsonReWriter.php
+++ b/sources/classes/JsonReWriter.php
@@ -4,6 +4,9 @@ namespace goodboyalex\php_components_pack\classes;
use goodboyalex\php_components_pack\enums\JsonErrorCode;
use goodboyalex\php_components_pack\exceptions\JsonException;
+use goodboyalex\php_components_pack\traits\JsonReWriter\JsonReWriterDeleteTrait;
+use goodboyalex\php_components_pack\traits\JsonReWriter\JsonReWriterKeyTrait;
+use goodboyalex\php_components_pack\traits\JsonReWriter\JsonReWriterLoadSaveTrait;
use goodboyalex\php_components_pack\traits\JsonReWriter\JsonReWriterReadTrait;
use goodboyalex\php_components_pack\traits\JsonReWriter\JsonReWriterWriteTrait;
@@ -22,6 +25,11 @@ final class JsonReWriter
*/
public string $JsonString {
get {
+ // Проверка на пустоту
+ if (count($this->JsonData) === 0)
+ // - если массив пуст, возвращаем пустой JSON
+ return '{}';
+
// Преобразую данные в JSON
$json = json_encode($this->JsonData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
@@ -65,107 +73,18 @@ final class JsonReWriter
unset($this->JsonData);
}
- /**
- * Сохраняем JSON в файл.
- *
- * @param string $fileName Имя файла.
- *
- * @return bool Сохранены ли данные в файл: true
- да, false
- нет.
- */
- public function SaveToFile (string $fileName): bool
- {
- // Запись данных в файл
- return file_put_contents($fileName, $this->JsonString) !== false;
- }
-
- /**
- * Загрузка данных из JSON-файла.
- *
- * @param string $fileName Имя файла.
- *
- * @return bool Загрузились ли данные из файла: true
- да, false
- нет.
- */
- public function LoadFromFile (string $fileName): bool
- {
- // Проверка существования файла
- if (!is_file($fileName))
- // - если нет, возвращаем false
- return false;
-
- // Чтение содержимого файла
- $result = file_get_contents($fileName);
-
- // Проверка на ошибки
- if ($result === false)
- // - если есть ошибки, возвращаем false
- return false;
-
- // Записываем результат
- $this->JsonString = $result;
-
- // Возвращаем true, если все хорошо
- return true;
- }
-
- /**
- * Проверяем наличие ключа в JSON.
- *
- * @param string $key Ключ.
- *
- * @return bool true если ключ найден, false если нет.
- */
- public function IsKeyExists (string $key): bool
- {
- // Получаем массив ключей по вложенности
- $keys = $this->ParseKey($key);
-
- // Получаем текущий массив данных
- $current = $this->JsonData;
-
- // Для каждого ключа
- foreach ($keys as $key) {
- // - проверяем наличие ключа в текущем массиве
- if (!array_key_exists($key, $current))
- // - нет? Возвращаем false
- return false;
-
- // Переходим ко вложенному массиву
- $current = $current[$key];
- }
-
- // Возвращаем true, если все ключи найдены
- return true;
- }
-
- /**
- * Получение ключей по вложенности. Т.е., ключи вида "key1/key2/key3" => ["key1", "key2", "key3"]
.
- *
- * @param string $key Ключ.
- *
- * @return array Ключи по вложенности.
- */
- private function ParseKey (string $key): array
- {
- return explode('/', $key);
- }
-
- /**
- * Создание ключа в JSON.
- *
- * @param string $key Ключ.
- * @param mixed $value Значение.
- *
- * @return void
- * @throws JsonException Если ключ не является массивом.
- */
- private function CreateKey (string $key, mixed $value): void
- {
-
- }
-
// Подключаем методы чтения JSON
use JsonReWriterReadTrait;
// Подключаем методы записи JSON
use JsonReWriterWriteTrait;
+
+ // Подключаем методы сохранения и загрузки JSON
+ use JsonReWriterLoadSaveTrait;
+
+ // Подключаем методы работы с ключами
+ use JsonReWriterKeyTrait;
+
+ // Подключаем методы удаления данных из JSON
+ use JsonReWriterDeleteTrait;
}
\ No newline at end of file
diff --git a/sources/enums/JsonErrorCode.php b/sources/enums/JsonErrorCode.php
index 88f7ea9..2348c12 100644
--- a/sources/enums/JsonErrorCode.php
+++ b/sources/enums/JsonErrorCode.php
@@ -70,7 +70,7 @@ enum JsonErrorCode: int
/**
* Имя свойства не может быть закодировано.
*/
- case INVALID_PROPERTY_NAME = 9;
+ case InvalidPropertyName = 9;
/**
* Некорректный для кодировки UTF-16 символ, возможно, некорректно закодирован.
diff --git a/sources/traits/JsonReWriter/JsonReWriterDeleteTrait.php b/sources/traits/JsonReWriter/JsonReWriterDeleteTrait.php
new file mode 100644
index 0000000..b8c0e8b
--- /dev/null
+++ b/sources/traits/JsonReWriter/JsonReWriterDeleteTrait.php
@@ -0,0 +1,69 @@
+JsonData);
+
+ // Создание пустого массива
+ $this->JsonData = [];
+ }
+
+ /**
+ * Удаление ключа JSON.
+ *
+ * @param string $key Требуемый ключ JSON для удаления.
+ *
+ * @return bool Результат удаления ключа: true
- удаление прошло успешно, false
-
+ * произошла ошибка при удалении.
+ */
+ public function DeleteKey (string $key): bool
+ {
+ // Очищаем ключ
+ $preparedKey = $this->PrepareKey($key);
+
+ // Проверка ключа
+ if (!$this->IsKeyExists($preparedKey))
+ // - ключ не существует
+ return false;
+
+ // Разбиваем ключ на части
+ $keys = $this->ParseKey($preparedKey);
+
+ // Получаем текущий массив данных
+ $current = &$this->JsonData;
+
+ // Если ключ не является корневым
+ if (count($keys) > 0)
+ // - переходим к вложенному массиву
+ for ($i = 0; $i < count($keys) - 1; $i++)
+ // -- и добавляем массив данных
+ $current = &$current[$keys[$i]];
+
+ // Получаем удаляемый ключ
+ $deleteKey = $keys[count($keys) - 1];
+
+ // Удаляем ключ
+ unset($current[$deleteKey]);
+
+ // Проверяем удаление
+ return $this->IsKeyExists($key);
+ }
+}
\ No newline at end of file
diff --git a/sources/traits/JsonReWriter/JsonReWriterKeyTrait.php b/sources/traits/JsonReWriter/JsonReWriterKeyTrait.php
new file mode 100644
index 0000000..d3fd41c
--- /dev/null
+++ b/sources/traits/JsonReWriter/JsonReWriterKeyTrait.php
@@ -0,0 +1,129 @@
+ParseKey($key);
+
+ // Получаем текущий массив данных
+ $current = $this->JsonData;
+
+ // Для каждого ключа
+ foreach ($keys as $key) {
+ // - проверяем наличие ключа в текущем массиве
+ if (!array_key_exists($key, $current))
+ // - нет? Возвращаем false
+ return false;
+
+ // Переходим ко вложенному массиву
+ $current = $current[$key];
+ }
+
+ // Возвращаем true, если все ключи найдены
+ return true;
+ }
+
+ /**
+ * Получение ключей по вложенности. Т.е., ключи вида "key1/key2/key3" => ["key1", "key2", "key3"]
.
+ *
+ * @param string $key Ключ.
+ *
+ * @return array Ключи по вложенности.
+ */
+ private function ParseKey (string $key): array
+ {
+ // Очищаем ключ
+ $key = $this->PrepareKey($key);
+
+ // Разбиваем ключ на части
+ return explode('/', $key);
+ }
+
+ /**
+ * Подготавливает ключ к использованию внутри методов.
+ *
+ * @param string $key Неочищенный ключ.
+ *
+ * @return string Очищенный ключ.
+ */
+ private function PrepareKey (string $key): string
+ {
+ return trim($key, "/ ");
+ }
+
+ /**
+ * Получение списка ключей.
+ *
+ * @param string $parentKey Ключ родителя (или "" (установлено по умолчанию) для всех).
+ * @param bool $includeChildren Нужно ли включать дочерние ключи (по умолчанию, да).
+ *
+ * @return array Список ключей.
+ */
+ public function GetKeys (string $parentKey = "", bool $includeChildren = true): array
+ {
+ // Очищаем ключ
+ $parentKey = $this->PrepareKey($parentKey);
+
+ // Разбиваем ключ на части
+ $keys = StringExtension::IsNullOrWhitespace($parentKey) ? [] : $this->ParseKey($parentKey);
+
+ // Получаем текущий массив данных
+ $current = $this->JsonData;
+
+ // Если ключ не является корневым
+ if (count($keys) > 0)
+ // - переходим к вложенному массиву
+ for ($i = 0; $i < count($keys); $i++)
+ // -- и добавляем массив данных
+ $current = $current[$keys[$i]];
+
+ // Получаем список ключей родителя
+ $parentKeysList = array_keys($current);
+
+ // Если не нужно включать дочерние ключи
+ if (!$includeChildren)
+ // - возвращаем список родительских ключей
+ return $parentKeysList;
+
+ // Создаем результирующий массив
+ $result = [];
+
+ // Для каждого ключа
+ foreach ($parentKeysList as $key) {
+ // - очищаем текущий ключ
+ $currentKey = $this->PrepareKey($parentKey . "/" . $key);
+
+ // - добавляем его в результирующий массив
+ $result[] = $currentKey;
+
+ // - если у текущего ключа есть дочерние ключи
+ if (is_array($current[$key]))
+ // -- добавляем их в результирующий массив
+ $result = array_merge($result, $this->GetKeys($currentKey));
+ }
+
+ // Возвращаем результирующий массив
+ return $result;
+ }
+}
\ No newline at end of file
diff --git a/sources/traits/JsonReWriter/JsonReWriterLoadSaveTrait.php b/sources/traits/JsonReWriter/JsonReWriterLoadSaveTrait.php
new file mode 100644
index 0000000..52e27e7
--- /dev/null
+++ b/sources/traits/JsonReWriter/JsonReWriterLoadSaveTrait.php
@@ -0,0 +1,56 @@
+true - да, false
- нет.
+ */
+ public function SaveToFile (string $fileName): bool
+ {
+ // Запись данных в файл
+ return file_put_contents($fileName, $this->JsonString) !== false;
+ }
+
+ /**
+ * Загрузка данных из JSON-файла.
+ *
+ * @param string $fileName Имя файла.
+ *
+ * @return bool Загрузились ли данные из файла: true
- да, false
- нет.
+ */
+ public function LoadFromFile (string $fileName): bool
+ {
+ // Проверка существования файла
+ if (!is_file($fileName))
+ // - если нет, возвращаем false
+ return false;
+
+ // Чтение содержимого файла
+ $result = file_get_contents($fileName);
+
+ // Проверка на ошибки
+ if ($result === false)
+ // - если есть ошибки, возвращаем false
+ return false;
+
+ // Записываем результат
+ $this->JsonString = $result;
+
+ // Возвращаем true, если все хорошо
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/sources/traits/JsonReWriter/JsonReWriterReadTrait.php b/sources/traits/JsonReWriter/JsonReWriterReadTrait.php
index 5590b5e..1cdc8cc 100644
--- a/sources/traits/JsonReWriter/JsonReWriterReadTrait.php
+++ b/sources/traits/JsonReWriter/JsonReWriterReadTrait.php
@@ -39,6 +39,9 @@ trait JsonReWriterReadTrait
*/
public function Read (string $key, mixed $default = null): mixed
{
+ // Подготавливаем ключ
+ $key = $this->PrepareKey($key);
+
// Проверяем, существует ли ключ
if (!$this->IsKeyExists($key))
// - если нет, то возвращаем значение по умолчанию
@@ -53,7 +56,7 @@ trait JsonReWriterReadTrait
// Для каждого ключа до предпоследнего
for ($i = 0; $i < count($keys) - 1; $i++)
// - переходим ко вложенному массиву
- $current = &$current[$keys[$i]];
+ $current = $current[$keys[$i]];
// Возвращаем значение последнего ключа и если его нет, то возвращаем значение по умолчанию
return $current[$keys[count($keys) - 1]] ?? $default;
@@ -95,7 +98,27 @@ trait JsonReWriterReadTrait
*/
public function ReadArray (string $key, array $default = []): array
{
- return (array)$this->Read($key, $default);
+ // Получаем значение ключа JSON
+ $serializedDef = json_encode($default);
+
+ // Читаем значение ключа JSON
+ $value = $this->ReadString($key, $serializedDef);
+
+ // Десериализуем значение ключа JSON
+ return json_decode($value, true);
+ }
+
+ /**
+ * Читает значение ключа JSON как строку.
+ *
+ * @param string $key Ключ JSON.
+ * @param string $default Значение по умолчанию.
+ *
+ * @return string Значение ключа JSON или значение по умолчанию.
+ */
+ public function ReadString (string $key, string $default = ""): string
+ {
+ return (string)$this->Read($key, $default);
}
/**
@@ -108,7 +131,14 @@ trait JsonReWriterReadTrait
*/
public function ReadObject (string $key, object $default): object
{
- return (object)$this->Read($key, $default);
+ // Получаем значение ключа JSON
+ $serializedDef = json_encode($default);
+
+ // Читаем значение ключа JSON
+ $value = $this->ReadString($key, $serializedDef);
+
+ // Десериализуем значение ключа JSON
+ return json_decode($value);
}
/**
@@ -140,17 +170,4 @@ trait JsonReWriterReadTrait
// Возвращаем объект
return $instance;
}
-
- /**
- * Читает значение ключа JSON как строку.
- *
- * @param string $key Ключ JSON.
- * @param string $default Значение по умолчанию.
- *
- * @return string Значение ключа JSON или значение по умолчанию.
- */
- public function ReadString (string $key, string $default = ""): string
- {
- return (string)$this->Read($key, $default);
- }
}
\ No newline at end of file
diff --git a/sources/traits/JsonReWriter/JsonReWriterWriteTrait.php b/sources/traits/JsonReWriter/JsonReWriterWriteTrait.php
index 6d2f206..0ceaaf0 100644
--- a/sources/traits/JsonReWriter/JsonReWriterWriteTrait.php
+++ b/sources/traits/JsonReWriter/JsonReWriterWriteTrait.php
@@ -41,6 +41,9 @@ trait JsonReWriterWriteTrait
*/
public function Write (string $key, mixed $value): void
{
+ // Подготавливаем ключ
+ $key = $this->PrepareKey($key);
+
// Получаем массив ключей по вложенности
$keys = $this->ParseKey($key);
@@ -85,4 +88,22 @@ trait JsonReWriterWriteTrait
// Записываем в ключ
$this->Write($key, $serialized);
}
+
+ /**
+ * Записывает массив в ключ JSON.
+ *
+ * @param string $key Ключ JSON.
+ * @param array $array Массив для записи.
+ *
+ * @return void
+ * @throws JsonException Ключ не содержит вложений, хотя от него требуется обратное.
+ */
+ public function WriteArray (string $key, array $array): void
+ {
+ // Сериализуем массив
+ $serialized = json_encode($array);
+
+ // Записываем в ключ
+ $this->Write($key, $serialized);
+ }
}
\ No newline at end of file
diff --git a/tests/classes/JsonReWriterTest.php b/tests/classes/JsonReWriterTest.php
index f415271..e067d99 100644
--- a/tests/classes/JsonReWriterTest.php
+++ b/tests/classes/JsonReWriterTest.php
@@ -2,28 +2,318 @@
namespace goodboyalex\php_components_pack\tests\classes;
+use goodboyalex\php_components_pack\classes\File;
use goodboyalex\php_components_pack\classes\JsonReWriter;
+use goodboyalex\php_components_pack\exceptions\JsonException;
+use goodboyalex\php_components_pack\tests\data\A;
+use goodboyalex\php_components_pack\tests\data\C;
use PHPUnit\Framework\TestCase;
class JsonReWriterTest extends TestCase
{
- public function testSaveToFile ()
+ public function testIsKeyExists ()
{
$this->PrepareForTest();
$json = new JsonReWriter();
- $json->Write("test/subtest/AAA", "123");
- $json->SaveToFile(__DIR__ . '/test.json');
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $this->assertTrue($json->IsKeyExists("test/subtest/AAA"));
}
private function PrepareForTest (): void
{
require_once __DIR__ . '/../../sources/exceptions/JsonException.php';
+ require_once __DIR__ . '/../../sources/traits/JsonReWriter/JsonReWriterDeleteTrait.php';
+ require_once __DIR__ . '/../../sources/traits/JsonReWriter/JsonReWriterKeyTrait.php';
+ require_once __DIR__ . '/../../sources/traits/JsonReWriter/JsonReWriterLoadSaveTrait.php';
+ require_once __DIR__ . '/../../sources/traits/JsonReWriter/JsonReWriterReadTrait.php';
+ require_once __DIR__ . '/../../sources/traits/JsonReWriter/JsonReWriterWriteTrait.php';
require_once __DIR__ . '/../../sources/classes/JsonReWriter.php';
+ require_once __DIR__ . '/../data/A.php';
+ require_once __DIR__ . '/../data/C.php';
+ }
+
+ public function testReadWriteInt ()
+ {
+ $this->PrepareForTest();
+
+ $json = new JsonReWriter();
+ try {
+ $json->Write("test/test", 123);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $this->assertEquals(123, $json->ReadInt("test/test"));
+ }
+
+ public function testReadWriteBool ()
+ {
+ $this->PrepareForTest();
+
+ $json = new JsonReWriter();
+ try {
+ $json->Write("test/test1", false);
+ $json->Write("test/test2", true);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $this->assertTrue($json->ReadBool("test/test2"));
+ $this->assertFalse($json->ReadBool("test/test1"));
+ }
+
+ public function testReadWriteString ()
+ {
+ $this->PrepareForTest();
+
+ $json = new JsonReWriter();
+ try {
+ $json->Write("test/test", "test string");
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $this->assertEquals("test string", $json->ReadString("test/test", "test this"));
+ }
+
+ public function testSaveToFile ()
+ {
+ $this->PrepareForTest();
+
+ $fileName = __DIR__ . "/test.json";
+
+ if (file_exists($fileName))
+ unlink($fileName);
+
+ $json = new JsonReWriter();
+
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $json->SaveToFile($fileName);
+
+ $this->assertFileExists($fileName);
+
+ $size = File::FileSize($fileName)->Value;
+
+ $this->assertEquals(268, $size);
+
+ unlink($fileName);
+ }
+
+ public function testReadWriteArray ()
+ {
+ $this->PrepareForTest();
+
+ $json = new JsonReWriter();
+
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $this->assertArrayIsEqualToArrayIgnoringListOfKeys([1, 2, 3], $json->ReadArray("test3/test/res"), []);
+ }
+
+ public function testClear ()
+ {
+ $this->PrepareForTest();
+
+ $json = new JsonReWriter();
+
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $json->Clear();
+
+ $this->assertCount(0, $json->GetKeys());
+ }
+
+ public function testReadWriteObject ()
+ {
+ $this->PrepareForTest();
+
+ $json = new JsonReWriter();
+
+ $class = new A("test", 123, true);
+
+ try {
+ $json->WriteObject("test", $class);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $this->assertEquals("test", $json->ReadObject("test", new A())->a);
}
public function testLoadFromFile ()
{
+ $this->PrepareForTest();
+ $fileName = __DIR__ . "/test.json";
+
+ if (file_exists($fileName))
+ unlink($fileName);
+
+ $json = new JsonReWriter();
+
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $json->SaveToFile($fileName);
+
+ unset($json);
+
+ $json = new JsonReWriter();
+
+ $json->LoadFromFile($fileName);
+
+ unlink($fileName);
+
+ $this->assertEquals(123, $json->ReadInt("test1/test"));
+ }
+
+ public function testDeleteKey ()
+ {
+ $this->PrepareForTest();
+
+ $json = new JsonReWriter();
+
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $json->DeleteKey("test3/test/res");
+
+ $this->assertFalse($json->IsKeyExists("test3/test/res"));
+ }
+
+ public function testReadWrite ()
+ {
+ $this->PrepareForTest();
+
+ $json = new JsonReWriter();
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->Write("test3/test/res", json_encode([1, 2, 3]));
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $this->assertTrue($json->IsKeyExists("test/subtest/AAA"));
+ $this->assertTrue($json->IsKeyExists("test1/test"));
+ $this->assertEquals(1.23, (float)$json->Read("test/subtest/BBB"));
+ }
+
+ public function testGetKeys ()
+ {
+ $this->PrepareForTest();
+
+ $json = new JsonReWriter();
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $this->assertCount(11, $json->GetKeys());
+ $this->assertCount(2, $json->GetKeys("test/subtest"));
+ }
+
+ public function testReadWriteSerializable ()
+ {
+ $this->PrepareForTest();
+
+ $serializableClass = new C("test", 123, true);
+
+ $json = new JsonReWriter();
+ try {
+ $json->WriteSerializable("test", $serializableClass);
+
+ /**
+ * @var C $unSerializableClass Получаем объект из файла
+ */
+ $unSerializableClass = $json->ReadSerializable("test", "goodboyalex\\php_components_pack\\tests\\data\\C");
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ return;
+ }
+
+ $this->assertEquals($serializableClass->stringC, $unSerializableClass->stringC);
+ $this->assertEquals($serializableClass->intC, $unSerializableClass->intC);
+ $this->assertEquals($serializableClass->boolC, $unSerializableClass->boolC);
+ }
+
+ public function testReadWriteFloat ()
+ {
+ $this->PrepareForTest();
+
+ $json = new JsonReWriter();
+ try {
+ $json->Write("test", 1.23);
+ }
+ catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ $this->assertEquals(1.23, $json->ReadFloat("test", 0.2));
}
}
\ No newline at end of file
diff --git a/tests/data/C.php b/tests/data/C.php
new file mode 100644
index 0000000..790355e
--- /dev/null
+++ b/tests/data/C.php
@@ -0,0 +1,36 @@
+stringC = $string;
+ $this->intC = $int;
+ $this->boolC = $bool;
+ }
+
+ public function Serialize (): string
+ {
+ $array = [];
+ $array["string"] = $this->stringC;
+ $array["int"] = $this->intC;
+ $array["bool"] = $this->boolC;
+ return json_encode($array);
+ }
+
+ public function UnSerialize (string $serialized): void
+ {
+ $array = json_decode($serialized, true);
+ $this->stringC = $array["string"];
+ $this->intC = $array["int"];
+ $this->boolC = $array["bool"];
+ }
+}
\ No newline at end of file