diff --git a/sources/classes/JsonReWriter.php b/sources/classes/JsonReWriter.php
index bf406a9..49e7011 100644
--- a/sources/classes/JsonReWriter.php
+++ b/sources/classes/JsonReWriter.php
@@ -2,8 +2,10 @@
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\JsonReWriterReadTrait;
+use goodboyalex\php_components_pack\traits\JsonReWriter\JsonReWriterWriteTrait;
/**
* Класс для работы с JSON-файлами.
@@ -15,10 +17,37 @@ use goodboyalex\php_components_pack\traits\JsonReWriter\JsonReWriterReadTrait;
*/
final class JsonReWriter
{
+ /**
+ * @var string $JsonString Строка JSON.
+ */
+ public string $JsonString {
+ get {
+ // Преобразую данные в JSON
+ $json = json_encode($this->JsonData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
+
+ // Проверка на ошибки
+ if (json_last_error() !== JSON_ERROR_NONE)
+ // - если есть ошибки, выбрасываем исключение
+ throw new JsonException(null, JsonErrorCode::FromLastError(), json_last_error_msg());
+
+ // Возвращаем JSON
+ return $json;
+ }
+ set {
+ // Чтение содержимого файла и преобразование JSON в объект
+ $this->JsonData = json_decode($value, true);
+
+ // Проверка на ошибки
+ if ($this->JsonData === null && json_last_error() !== JSON_ERROR_NONE)
+ // - если есть ошибки, выбрасываем исключение
+ throw new JsonException($value, JsonErrorCode::FromLastError(), json_last_error_msg());
+ }
+ }
+
/**
* @var array $JsonData Массив данных.
*/
- public array $JsonData;
+ private array $JsonData;
/**
* Конструктор класса.
@@ -41,18 +70,12 @@ final class JsonReWriter
*
* @param string $fileName Имя файла.
*
- * @return void
- * @throws JsonException Если файл не может быть сохранен.
+ * @return bool Сохранены ли данные в файл: true
- да, false
- нет.
*/
- public function SaveToFile (string $fileName): void
+ public function SaveToFile (string $fileName): bool
{
// Запись данных в файл
- file_put_contents($fileName, json_encode($this->JsonData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
-
- // Проверка на ошибки
- if (json_last_error() !== JSON_ERROR_NONE)
- // - если есть ошибки, выбрасываем исключение
- throw new JsonException($fileName, json_last_error(), json_last_error_msg());
+ return file_put_contents($fileName, $this->JsonString) !== false;
}
/**
@@ -60,23 +83,28 @@ final class JsonReWriter
*
* @param string $fileName Имя файла.
*
- * @return void
- * @throws JsonException Если файл не существует или содержит ошибки.
+ * @return bool Загрузились ли данные из файла: true
- да, false
- нет.
*/
- public function LoadFromFile (string $fileName): void
+ public function LoadFromFile (string $fileName): bool
{
// Проверка существования файла
if (!is_file($fileName))
- // - нет? Выбрасываем исключение
- throw new JsonException($fileName, -1, "File does not exist / Файл не существует");
+ // - если нет, возвращаем false
+ return false;
- // Чтение содержимого файла и преобразование JSON в объект
- $this->JsonData = json_decode(file_get_contents($fileName), true);
+ // Чтение содержимого файла
+ $result = file_get_contents($fileName);
// Проверка на ошибки
- if ($this->JsonData === null && json_last_error() !== JSON_ERROR_NONE)
- // - если есть ошибки, выбрасываем исключение
- throw new JsonException($fileName, json_last_error(), json_last_error_msg());
+ if ($result === false)
+ // - если есть ошибки, возвращаем false
+ return false;
+
+ // Записываем результат
+ $this->JsonString = $result;
+
+ // Возвращаем true, если все хорошо
+ return true;
}
/**
@@ -132,32 +160,12 @@ final class JsonReWriter
*/
private function CreateKey (string $key, mixed $value): void
{
- // Получаем массив ключей по вложенности
- $keys = $this->ParseKey($key);
- // Получаем текущий массив данных
- $current = &$this->JsonData;
-
- // Для каждого ключа до предпоследнего
- for ($i = 0; $i < count($keys) - 1; $i++) {
- // - проверяем наличие ключа в текущем массиве
- if (!isset($current[$keys[$i]]))
- // - нет? Создаем ключ (массив)
- $current[$keys[$i]] = [];
-
- // - проверяем, что ключ является массивом
- if (!is_array($current[$keys[$i]]))
- // - нет? Выбрасываем исключение
- throw new JsonException(null, -1, "Key is not an array / Ключ не является массивом!");
-
- // - переходим ко вложенному массиву
- $current = &$current[$keys[$i]];
- }
-
- // Создаем ключ (значение)
- $current[$keys[count($keys) - 1]] = $value;
}
-
+
// Подключаем методы чтения JSON
use JsonReWriterReadTrait;
+
+ // Подключаем методы записи JSON
+ use JsonReWriterWriteTrait;
}
\ No newline at end of file
diff --git a/sources/enums/JsonErrorCode.php b/sources/enums/JsonErrorCode.php
new file mode 100644
index 0000000..88f7ea9
--- /dev/null
+++ b/sources/enums/JsonErrorCode.php
@@ -0,0 +1,108 @@
+ 10)
+ // - верну неизвестную ошибку, если код не в диапазоне
+ return self::Unknown;
+
+ // Перевожу код в Enum
+ return self::FromInt($error);
+ }
+}
\ No newline at end of file
diff --git a/sources/exceptions/JsonException.php b/sources/exceptions/JsonException.php
index b3b3109..9831dc8 100644
--- a/sources/exceptions/JsonException.php
+++ b/sources/exceptions/JsonException.php
@@ -3,6 +3,7 @@
namespace goodboyalex\php_components_pack\exceptions;
use Exception;
+use goodboyalex\php_components_pack\enums\JsonErrorCode;
/**
* Ошибка работы с JSON.
@@ -15,33 +16,32 @@ use Exception;
final class JsonException extends Exception
{
/**
- * @var string|null $JsonFileName Имя файла JSON.
+ * @var string|null $JsonString Строка JSON.
*/
- public ?string $JsonFileName;
+ public ?string $JsonString;
/**
- * @link https://www.php.net/manual/ru/function.json-last-error.php
- * @var int $JsonErrorCode Код ошибки JSON.
+ * @var JsonErrorCode $ErrorCode Код ошибки JSON.
*/
- public int $JsonErrorCode;
+ public JsonErrorCode $ErrorCode;
/**
* @link https://www.php.net/manual/ru/function.json-last-error-msg.php
- * @var string|null $JsonErrorMessage Сообщение об ошибке JSON.
+ * @var string|null $ErrorMessage Сообщение об ошибке JSON.
*
* Внимание! В отличие от функции json_last_error_msg(), данная переменная при отсутствии ошибок выводит null, а не
* "No error".
*/
- public ?string $JsonErrorMessage;
+ public ?string $ErrorMessage;
/**
* Конструктор.
*
- * @param string|null $fileName Имя файла JSON.
- * @param int $errorCode Код ошибки JSON.
+ * @param string|null $json Строка JSON.
+ * @param JsonErrorCode $errorCode Код ошибки JSON.
* @param string|null $errorMessage Сообщение об ошибке JSON.
*/
- public function __construct (?string $fileName = null, int $errorCode = JSON_ERROR_NONE,
+ public function __construct (?string $json = null, JsonErrorCode $errorCode = JsonErrorCode::Unknown,
?string $errorMessage = null)
{
// Если код ошибки JSON равен 0
@@ -50,7 +50,7 @@ final class JsonException extends Exception
$errorMessage = null;
// Сохраняем сообщение об ошибке
- $this->JsonErrorMessage = $errorMessage;
+ $this->ErrorMessage = $errorMessage;
// Если сообщение пусто, то присваиваем ему "" для совместимости
$errorMessage = $errorMessage ?? "";
@@ -59,9 +59,9 @@ final class JsonException extends Exception
parent::__construct($errorMessage);
// Присваиваем имя файла
- $this->JsonFileName = $fileName;
+ $this->JsonString = $json;
// Присваиваем код ошибки
- $this->JsonErrorCode = $errorCode;
+ $this->ErrorCode = $errorCode;
}
}
\ No newline at end of file
diff --git a/sources/traits/JsonReWriter/JsonReWriterReadTrait.php b/sources/traits/JsonReWriter/JsonReWriterReadTrait.php
index 20a5b5d..5590b5e 100644
--- a/sources/traits/JsonReWriter/JsonReWriterReadTrait.php
+++ b/sources/traits/JsonReWriter/JsonReWriterReadTrait.php
@@ -2,6 +2,10 @@
namespace goodboyalex\php_components_pack\traits\JsonReWriter;
+use goodboyalex\php_components_pack\enums\JsonErrorCode;
+use goodboyalex\php_components_pack\exceptions\JsonException;
+use goodboyalex\php_components_pack\interfaces\ISerializable;
+
/**
* Часть кода класса JsonReWriter, отвечающая за методы чтения ключей и значений JSON.
*
@@ -35,9 +39,12 @@ trait JsonReWriterReadTrait
*/
public function Read (string $key, mixed $default = null): mixed
{
+ // Проверяем, существует ли ключ
if (!$this->IsKeyExists($key))
+ // - если нет, то возвращаем значение по умолчанию
return $default;
+ // Разбиваем ключ на массив ключей
$keys = $this->ParseKey($key);
// Получаем текущий массив данных
@@ -104,6 +111,36 @@ trait JsonReWriterReadTrait
return (object)$this->Read($key, $default);
}
+ /**
+ * Читает значение ключа JSON как объект, реализующий интерфейс ISerializable.
+ *
+ * @param string $key Ключ JSON.
+ * @param string $serializableClassName Имя класса, реализующего интерфейс ISerializable, с namespace.
+ *
+ * @return ISerializable Инициализированный объект
+ * @throws JsonException Если класс не реализует интерфейс ISerializable
+ */
+ public function ReadSerializable (string $key, string $serializableClassName): ISerializable
+ {
+ // Создаем объект
+ $instance = new $serializableClassName();
+
+ // Проверяем, что он реализует интерфейс ISerializable
+ if (!$instance instanceof ISerializable)
+ // - если нет, то выбрасываем исключение
+ throw new JsonException(errorCode: JsonErrorCode::NotISerializable,
+ errorMessage: "Class $serializableClassName is not implements ISerializable interface / Класс $serializableClassName не реализует интерфейс ISerializable");
+
+ // Получаем строку JSON из ключа
+ $json = $this->ReadString($key, $instance->Serialize());
+
+ // Десериализуем строку JSON в объект
+ $instance->UnSerialize($json);
+
+ // Возвращаем объект
+ return $instance;
+ }
+
/**
* Читает значение ключа JSON как строку.
*
diff --git a/sources/traits/JsonReWriter/JsonReWriterWriteTrait.php b/sources/traits/JsonReWriter/JsonReWriterWriteTrait.php
new file mode 100644
index 0000000..6d2f206
--- /dev/null
+++ b/sources/traits/JsonReWriter/JsonReWriterWriteTrait.php
@@ -0,0 +1,88 @@
+Write($key, json_encode($value));
+ }
+
+ /**
+ * Записывает значение в ключ JSON.
+ *
+ * @param string $key Ключ JSON.
+ * @param mixed $value Записываемое значение.
+ *
+ * @return void
+ * @throws JsonException Ключ не содержит вложений, хотя от него требуется обратное.
+ */
+ public function Write (string $key, mixed $value): void
+ {
+ // Получаем массив ключей по вложенности
+ $keys = $this->ParseKey($key);
+
+ // Получаем текущий массив данных
+ $current = &$this->JsonData;
+
+ // Для каждого ключа до предпоследнего
+ for ($i = 0; $i < count($keys) - 1; $i++) {
+ // - проверяем наличие ключа в текущем массиве
+ if (!isset($current[$keys[$i]]))
+ // - нет? Создаем ключ (массив)
+ $current[$keys[$i]] = [];
+
+ // - проверяем, что ключ является массивом
+ if (!is_array($current[$keys[$i]]))
+ // - нет? Выбрасываем исключение
+ throw new JsonException(errorCode: JsonErrorCode::KeyIsNotArray,
+ errorMessage: "The key does not contain attachments, although it is required to do the opposite / Ключ не содержит вложений, хотя от него требуется обратное!");
+
+ // - переходим ко вложенному массиву
+ $current = &$current[$keys[$i]];
+ }
+
+ // Создаем ключ (значение)
+ $current[$keys[count($keys) - 1]] = $value;
+ }
+
+ /**
+ * Записывает объект, реализующий интерфейс ISerializable, в ключ JSON.
+ *
+ * @param string $key Ключ JSON.
+ * @param ISerializable $serializableValue Записываемый объект, реализующий интерфейс ISerializable.
+ *
+ * @return void
+ * @throws JsonException Ключ не содержит вложений, хотя от него требуется обратное.
+ */
+ public function WriteSerializable (string $key, ISerializable $serializableValue): void
+ {
+ // Сериализуем объект
+ $serialized = $serializableValue->Serialize();
+
+ // Записываем в ключ
+ $this->Write($key, $serialized);
+ }
+}
\ No newline at end of file
diff --git a/tests/classes/JsonReWriterTest.php b/tests/classes/JsonReWriterTest.php
index 7cd5591..f415271 100644
--- a/tests/classes/JsonReWriterTest.php
+++ b/tests/classes/JsonReWriterTest.php
@@ -12,11 +12,8 @@ class JsonReWriterTest extends TestCase
$this->PrepareForTest();
$json = new JsonReWriter();
- $json->CreateKey("test/subtest/AAA", "123");
-
- var_dump($json->JsonData);
-
- //$json->SaveToFile(__DIR__ . '/test.json');
+ $json->Write("test/subtest/AAA", "123");
+ $json->SaveToFile(__DIR__ . '/test.json');
}
private function PrepareForTest (): void
@@ -29,4 +26,4 @@ class JsonReWriterTest extends TestCase
{
}
-}
+}
\ No newline at end of file