20250628 1.1 Beta 2
This commit is contained in:
		| @@ -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 Сохранены ли данные в файл: <code>true</code> - да, <code>false</code> - нет. | ||||
|      */ | ||||
|     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 Загрузились ли данные из файла: <code>true</code> - да, <code>false</code> - нет. | ||||
|      */ | ||||
|     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; | ||||
| } | ||||
							
								
								
									
										108
									
								
								sources/enums/JsonErrorCode.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								sources/enums/JsonErrorCode.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\enums; | ||||
|  | ||||
| use goodboyalex\php_components_pack\traits\EnumExtensionsTrait; | ||||
|  | ||||
| /** | ||||
|  * Перечисление известных ошибок при работе с JSON файлами. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.1.0 | ||||
|  */ | ||||
| enum JsonErrorCode: int | ||||
| { | ||||
|     // Подключаю расширение для Enum | ||||
|     use EnumExtensionsTrait; | ||||
|  | ||||
|     /** | ||||
|      * Неизвестная ошибка. | ||||
|      */ | ||||
|     case Unknown = -1; | ||||
|  | ||||
|     /** | ||||
|      * Ошибок нет. | ||||
|      */ | ||||
|     case None = 0; | ||||
|  | ||||
|     /** | ||||
|      * Достигнута максимальная глубина стека. | ||||
|      */ | ||||
|     case Depth = 1; | ||||
|  | ||||
|     /** | ||||
|      * Неверный или некорректный JSON. | ||||
|      */ | ||||
|     case StateMismatch = 2; | ||||
|  | ||||
|     /** | ||||
|      * Ошибка управляющего символа, возможно, неверная кодировка. | ||||
|      */ | ||||
|     case CTRLChar = 3; | ||||
|  | ||||
|     /** | ||||
|      * Синтаксическая ошибка. | ||||
|      */ | ||||
|     case Syntax = 4; | ||||
|  | ||||
|     /** | ||||
|      * Некорректные для кодировки UTF-8 символы, возможно, неверная кодировка. | ||||
|      */ | ||||
|     case UTF8 = 5; | ||||
|  | ||||
|     /** | ||||
|      * Одна или несколько зацикленных ссылок в кодируемом значении. | ||||
|      */ | ||||
|     case Recursion = 6; | ||||
|  | ||||
|     /** | ||||
|      * Одно или несколько значений NAN или INF в кодируемом значении. | ||||
|      */ | ||||
|     case InfOrNan = 7; | ||||
|  | ||||
|     /** | ||||
|      * Передали значение с неподдерживаемым типом. | ||||
|      */ | ||||
|     case UnsupportedType = 8; | ||||
|  | ||||
|     /** | ||||
|      * Имя свойства не может быть закодировано. | ||||
|      */ | ||||
|     case INVALID_PROPERTY_NAME = 9; | ||||
|  | ||||
|     /** | ||||
|      * Некорректный для кодировки UTF-16 символ, возможно, некорректно закодирован. | ||||
|      */ | ||||
|     case UTF16 = 10; | ||||
|  | ||||
|     /** | ||||
|      * Ключ не содержит вложений, хотя от него требуется обратное. | ||||
|      */ | ||||
|     case KeyIsNotArray = 11; | ||||
|  | ||||
|     /** | ||||
|      * Класс не реализует интерфейс ISerializable. | ||||
|      */ | ||||
|     case NotISerializable = 12; | ||||
|  | ||||
|     /** | ||||
|      * Получает код ошибки из последней JSON ошибки. | ||||
|      * | ||||
|      * @return JsonErrorCode Код ошибки. | ||||
|      */ | ||||
|     public static function FromLastError (): JsonErrorCode | ||||
|     { | ||||
|         // Получаю код ошибки | ||||
|         $error = json_last_error(); | ||||
|  | ||||
|         // Проверяю, что код ошибки в диапазоне [0; 10] | ||||
|         if ($error < 0 || $error > 10) | ||||
|             // - верну неизвестную ошибку, если код не в диапазоне | ||||
|             return self::Unknown; | ||||
|  | ||||
|         // Перевожу код в Enum | ||||
|         return self::FromInt($error); | ||||
|     } | ||||
| } | ||||
| @@ -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; | ||||
|     } | ||||
| } | ||||
| @@ -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 как строку. | ||||
|      * | ||||
|   | ||||
							
								
								
									
										88
									
								
								sources/traits/JsonReWriter/JsonReWriterWriteTrait.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								sources/traits/JsonReWriter/JsonReWriterWriteTrait.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| <?php | ||||
|  | ||||
| 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. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.1.0 | ||||
|  */ | ||||
| trait JsonReWriterWriteTrait | ||||
| { | ||||
|     /** | ||||
|      * Записывает объект в ключ JSON. | ||||
|      * | ||||
|      * @param string $key Ключ JSON. | ||||
|      * @param object $value Записываемое значение. | ||||
|      * | ||||
|      * @return void | ||||
|      * @throws JsonException Ключ не содержит вложений, хотя от него требуется обратное. | ||||
|      */ | ||||
|     public function WriteObject (string $key, object $value): void | ||||
|     { | ||||
|         $this->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); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user