├── src ├── Exceptions │ ├── JsonErrorException.php │ ├── NoIterableFileException.php │ ├── NoIterableElementException.php │ ├── GetFileException.php │ ├── CreateFileException.php │ └── CreateDirectoryException.php └── Json.php ├── LICENSE ├── composer.json └── README.md /src/Exceptions/JsonErrorException.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace Josantonius\Json\Exceptions; 15 | 16 | class JsonErrorException extends \Exception 17 | { 18 | public function __construct() 19 | { 20 | $message = 'JSON error: ' . json_last_error_msg(); 21 | 22 | parent::__construct($message); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Exceptions/NoIterableFileException.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace Josantonius\Json\Exceptions; 15 | 16 | class NoIterableFileException extends \Exception 17 | { 18 | public function __construct(string $filepath, string $method) 19 | { 20 | parent::__construct( 21 | "The '$filepath' file doesn't contain an array to perform a '$method' operation on." 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Exceptions/NoIterableElementException.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace Josantonius\Json\Exceptions; 15 | 16 | class NoIterableElementException extends \Exception 17 | { 18 | public function __construct(string $dot, string $method) 19 | { 20 | parent::__construct( 21 | "The location specified by '$dot' dot is not an array to perform a '$method' operation on." 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Exceptions/GetFileException.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace Josantonius\Json\Exceptions; 15 | 16 | class GetFileException extends \Exception 17 | { 18 | public function __construct(string $filepath) 19 | { 20 | $lastError = error_get_last()['message'] ?? ''; 21 | 22 | $message = "Error reading file: '$filepath'."; 23 | $message .= $lastError ? " $lastError." : ''; 24 | 25 | parent::__construct($message); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Exceptions/CreateFileException.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace Josantonius\Json\Exceptions; 15 | 16 | class CreateFileException extends \Exception 17 | { 18 | public function __construct(string $filepath) 19 | { 20 | $lastError = error_get_last()['message'] ?? ''; 21 | 22 | $message = "Could not create file '$filepath'."; 23 | $message .= $lastError ? " $lastError." : ''; 24 | 25 | parent::__construct($message); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Exceptions/CreateDirectoryException.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace Josantonius\Json\Exceptions; 15 | 16 | class CreateDirectoryException extends \Exception 17 | { 18 | public function __construct(string $path) 19 | { 20 | $lastError = error_get_last()['message'] ?? ''; 21 | 22 | $message = "Could not create directory in '$path'."; 23 | $message .= $lastError ? " $lastError." : ''; 24 | 25 | parent::__construct($message); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright (c) 2016, Josantonius 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is furnished to do 11 | so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "josantonius/json", 3 | "description": "PHP simple library for managing Json files.", 4 | "license": "MIT", 5 | "type": "library", 6 | "keywords": [ 7 | "json", 8 | "file-to-array", 9 | "array-to-file", 10 | "php" 11 | ], 12 | "authors": [ 13 | { 14 | "name": "Josantonius", 15 | "email": "hello@josantonius.dev", 16 | "homepage": "https://josantonius.dev", 17 | "role": "Developer" 18 | } 19 | ], 20 | "support": { 21 | "issues": "https://github.com/josantonius/php-json/issues", 22 | "source": "https://github.com/josantonius/php-json", 23 | "discussions": "https://github.com/josantonius/php-json/discussions" 24 | }, 25 | "require": { 26 | "php": "^8.1" 27 | }, 28 | "require-dev": { 29 | "phpmd/phpmd": "^2.6", 30 | "phpunit/phpunit": "^9.5", 31 | "squizlabs/php_codesniffer": "^3.7" 32 | }, 33 | "minimum-stability": "stable", 34 | "autoload": { 35 | "psr-4": { 36 | "Josantonius\\Json\\": "src/" 37 | } 38 | }, 39 | "autoload-dev": { 40 | "psr-4": { 41 | "Josantonius\\Json\\Tests\\": "tests/" 42 | } 43 | }, 44 | "config": { 45 | "preferred-install": "dist" 46 | }, 47 | "extra": { 48 | "branch-alias": { 49 | "dev-master": "1.0-dev" 50 | } 51 | }, 52 | "scripts": { 53 | "coverage": "vendor/bin/phpunit --coverage-clover=coverage.xml", 54 | "fix": [ 55 | "vendor/bin/phpcbf src tests" 56 | ], 57 | "htmlCoverage": "vendor/bin/phpunit --coverage-html coverage", 58 | "phpcs": "vendor/bin/phpcs --standard=phpcs.xml $(find . -name '*.php');", 59 | "phpmd": "vendor/bin/phpmd src,tests text ./phpmd.xml", 60 | "phpunit": "vendor/bin/phpunit", 61 | "tests": [ 62 | "clear", 63 | "@phpmd", 64 | "@phpcs", 65 | "@phpunit" 66 | ] 67 | } 68 | } -------------------------------------------------------------------------------- /src/Json.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace Josantonius\Json; 15 | 16 | use Josantonius\Json\Exceptions\GetFileException; 17 | use Josantonius\Json\Exceptions\JsonErrorException; 18 | use Josantonius\Json\Exceptions\CreateFileException; 19 | use Josantonius\Json\Exceptions\NoIterableFileException; 20 | use Josantonius\Json\Exceptions\CreateDirectoryException; 21 | use Josantonius\Json\Exceptions\NoIterableElementException; 22 | 23 | /** 24 | * PHP simple library for managing JSON files. 25 | */ 26 | class Json 27 | { 28 | /** 29 | * Constructor method for the JSON file handling class. 30 | * 31 | * @param string $filepath The path to the JSON file to be handled. 32 | */ 33 | public function __construct(public readonly string $filepath) 34 | { 35 | } 36 | 37 | /** 38 | * Check if the file exists. 39 | * 40 | * @return bool True if the file exists at the specified filepath, false otherwise. 41 | */ 42 | public function exists(): bool 43 | { 44 | return file_exists($this->filepath); 45 | } 46 | 47 | /** 48 | * Get the contents of the JSON file. 49 | * 50 | * @param bool $asObject If true and the value is an array, it is returned as an object. 51 | * 52 | * @throws GetFileException if file reading failed. 53 | * @throws JsonErrorException if the file contains invalid JSON. 54 | * 55 | * @return mixed the contents of the JSON file. 56 | */ 57 | public function get(bool $asObject = false): mixed 58 | { 59 | $json = @file_get_contents($this->filepath); 60 | 61 | $json === false && throw new GetFileException($this->filepath); 62 | 63 | $array = json_decode($json, !$asObject); 64 | 65 | json_last_error() && throw new JsonErrorException(); 66 | 67 | return $array; 68 | } 69 | 70 | /** 71 | * Set the contents of a JSON or a key within the file. 72 | * 73 | * @param mixed $content The data that will be written to the file or a key within the file. 74 | * @param string $dot The dot notation representing the key to be modified within the file. 75 | * 76 | * @throws GetFileException if file reading failed. 77 | * @throws JsonErrorException if the file contains invalid JSON. 78 | * @throws CreateFileException if file creation failed. 79 | * @throws CreateDirectoryException if directory creation failed. 80 | * @throws NoIterableElementException if $dot isn't an array location. 81 | * 82 | * @return mixed the content of the JSON file after the set operation. 83 | */ 84 | public function set(mixed $content = [], string $dot = null): array|bool|int|null|string 85 | { 86 | $data = $dot !== null ? $this->get() : $content; 87 | 88 | if ($dot !== null) { 89 | $this->failIfNotArray(__FUNCTION__, $data, $dot); 90 | $this->modifyArrayByDot(__FUNCTION__, $data, $dot, $content); 91 | } 92 | 93 | return $this->saveToJsonFile($data); 94 | } 95 | 96 | /** 97 | * Merge the provided data with the contents of a JSON file or a key within the file. 98 | * 99 | * @param mixed $content The data that will be written to the file or a key within the file. 100 | * @param string $dot The dot notation representing the key to be modified within the file. 101 | * 102 | * @throws GetFileException if file reading failed. 103 | * @throws JsonErrorException if the file contains invalid JSON. 104 | * @throws NoIterableFileException if the file isn't a JSON array. 105 | * @throws NoIterableElementException if $dot isn't an array location. 106 | * 107 | * @return mixed the content of the JSON file after the merge operation. 108 | */ 109 | public function merge(array|object $content, string $dot = null): array 110 | { 111 | $data = $this->get(); 112 | 113 | $this->failIfNotArray(__FUNCTION__, $data, $this->filepath); 114 | 115 | if ($dot !== null) { 116 | $this->modifyArrayByDot(__FUNCTION__, $data, $dot, $content); 117 | return $this->saveToJsonFile($data); 118 | } 119 | 120 | return $this->saveToJsonFile(array_merge($data, (array) $content)); 121 | } 122 | 123 | /** 124 | * Remove and get the last element of a JSON file or a key within the file. 125 | * 126 | * @param string $dot The dot notation representing the key to be modified within the file. 127 | * 128 | * @throws GetFileException if file reading failed. 129 | * @throws JsonErrorException if the file contains invalid JSON. 130 | * @throws NoIterableFileException if the file isn't a JSON array. 131 | * @throws NoIterableElementException if $dot isn't an array location. 132 | * 133 | * @return mixed|null the last value of JSON file, or null if array is empty. 134 | */ 135 | public function pop(string $dot = null): mixed 136 | { 137 | $data = $this->get(); 138 | 139 | if ($dot !== null) { 140 | $value = $this->modifyArrayByDot(__FUNCTION__, $data, $dot); 141 | $this->saveToJsonFile($data); 142 | return $value; 143 | } 144 | 145 | $this->failIfNotArray(__FUNCTION__, $data, $this->filepath); 146 | $value = array_pop($data); 147 | $this->saveToJsonFile($data); 148 | return $value; 149 | } 150 | 151 | /** 152 | * Add the provided data to the end of the contents of a JSON file or a key within the file. 153 | * 154 | * @param mixed $content The data that will be written to the file or a key within the file. 155 | * @param string $dot The dot notation representing the key to be modified within the file. 156 | * 157 | * @throws GetFileException if file reading failed. 158 | * @throws JsonErrorException if the file contains invalid JSON. 159 | * @throws NoIterableFileException if the file isn't a JSON array. 160 | * @throws NoIterableElementException if $dot isn't an array location. 161 | * 162 | * @return mixed the content of the JSON file after the push operation. 163 | */ 164 | public function push(mixed $content, string $dot = null): array 165 | { 166 | $data = $this->get(); 167 | 168 | $this->failIfNotArray(__FUNCTION__, $data, $this->filepath); 169 | 170 | if ($dot !== null) { 171 | $this->modifyArrayByDot(__FUNCTION__, $data, $dot, $content); 172 | return $this->saveToJsonFile($data); 173 | } 174 | array_push($data, $content); 175 | 176 | return $this->saveToJsonFile($data); 177 | } 178 | 179 | /** 180 | * Remove and get the first element of a JSON file or a key within the file. 181 | * 182 | * @param string $dot The dot notation representing the key to be modified within the file. 183 | * 184 | * @throws GetFileException if file reading failed. 185 | * @throws JsonErrorException if the file contains invalid JSON. 186 | * @throws NoIterableFileException if the file isn't a JSON array. 187 | * @throws NoIterableElementException if $dot isn't an array location. 188 | * 189 | * @return mixed|null the shifted value, or null if array is empty. 190 | */ 191 | public function shift(string $dot = null): mixed 192 | { 193 | $data = $this->get(); 194 | 195 | if ($dot !== null) { 196 | $value = $this->modifyArrayByDot(__FUNCTION__, $data, $dot); 197 | $this->saveToJsonFile($data); 198 | return $value; 199 | } 200 | 201 | $this->failIfNotArray(__FUNCTION__, $data, $this->filepath); 202 | $value = array_shift($data); 203 | $this->saveToJsonFile($data); 204 | return $value; 205 | } 206 | 207 | /** 208 | * Remove a key and its value from the contents of a JSON file. 209 | * 210 | * @param string $dot The dot notation representing the key to be modified within the file. 211 | * @param bool $reindexed If true, the array will be re-indexed. 212 | * 213 | * @throws GetFileException if file reading failed. 214 | * @throws JsonErrorException if the file contains invalid JSON. 215 | * @throws NoIterableFileException if the file isn't a JSON array. 216 | * 217 | * @return array the content of the JSON file after the unset operation. 218 | */ 219 | public function unset(string $dot, bool $reindexed = false): array 220 | { 221 | $data = $this->get(); 222 | 223 | $this->failIfNotArray(__FUNCTION__, $data, $this->filepath); 224 | $this->modifyArrayByDot(__FUNCTION__, $data, $dot); 225 | 226 | return $this->saveToJsonFile($reindexed ? array_values($data) : $data); 227 | } 228 | 229 | /** 230 | * Add the provided data to the beginning of the contents of a JSON file or a key within the file. 231 | * 232 | * @param mixed $content The data that will be written to the file or a key within the file. 233 | * @param string $dot The dot notation representing the key to be modified within the file. 234 | * 235 | * @throws GetFileException if file reading failed. 236 | * @throws JsonErrorException if the file contains invalid JSON. 237 | * @throws NoIterableFileException if the file isn't a JSON array. 238 | * @throws NoIterableElementException if $dot isn't an array location. 239 | * 240 | * @return mixed the content of the JSON file after the unshift operation. 241 | */ 242 | public function unshift(mixed $content, string $dot = null): mixed 243 | { 244 | $data = $this->get(); 245 | 246 | $this->failIfNotArray(__FUNCTION__, $data, $this->filepath); 247 | 248 | if ($dot !== null) { 249 | $this->modifyArrayByDot(__FUNCTION__, $data, $dot, $content); 250 | return $this->saveToJsonFile($data); 251 | } 252 | array_unshift($data, $content); 253 | 254 | return $this->saveToJsonFile($data); 255 | } 256 | 257 | /** 258 | * Modify a nested array key by a dot notation string. 259 | * 260 | * @param string $type The type of operation to perform on the array. 261 | * @param mixed $array The array that will be modified. 262 | * @param mixed $dot The dot notation string representing the key of the nested array. 263 | * @param mixed $content The value that will be set or pushed to the array. 264 | * 265 | * @throws NoIterableElementException if $dot isn't an array location. 266 | * 267 | * @return mixed the contents that have been written to the file after the unshift operation. 268 | */ 269 | protected function modifyArrayByDot(string $type, array &$array, string $dot, mixed $content = []): mixed 270 | { 271 | $keys = explode('.', $dot); 272 | 273 | if ($type == 'unset') { 274 | $last = array_pop($keys); 275 | } 276 | 277 | foreach ($keys as $key) { 278 | $array = &$array[$key]; 279 | } 280 | 281 | if (!str_contains($type, 'set')) { 282 | $this->failIfNotArray($type, $array, $dot); 283 | } 284 | 285 | switch ($type) { 286 | case 'merge': 287 | $array = array_merge($array, (array) $content); 288 | break; 289 | case 'pop': 290 | return array_pop($array); 291 | case 'push': 292 | return array_push($array, is_object($content) ? (array) $content : $content); 293 | case 'set': 294 | $array = $content; 295 | break; 296 | case 'shift': 297 | return array_shift($array); 298 | case 'unset': 299 | unset($array[$last]); 300 | break; 301 | case 'unshift': 302 | return array_unshift($array, is_object($content) ? (array) $content : $content); 303 | } 304 | 305 | return null; 306 | } 307 | 308 | /** 309 | * Save contents to JSON file. 310 | * 311 | * @param mixed $content The data to be encoded as JSON and saved to the file. 312 | * 313 | * @throws CreateFileException if directory creation failed. 314 | * @throws CreateDirectoryException if file creation failed. 315 | * 316 | * @return mixed the contents that have been saved to the file. 317 | */ 318 | protected function saveToJsonFile(mixed $content): mixed 319 | { 320 | $json = json_encode($content, JSON_PRETTY_PRINT); 321 | $path = dirname($this->filepath) . DIRECTORY_SEPARATOR; 322 | 323 | if (!is_dir($path) && !@mkdir($path, 0777, true)) { 324 | throw new CreateDirectoryException($path); 325 | } 326 | 327 | if (@file_put_contents($this->filepath, $json) === false) { 328 | throw new CreateFileException($this->filepath); 329 | } 330 | 331 | return is_object($content) ? (array) $content : $content; 332 | } 333 | 334 | /** 335 | * Throws an exception if the element is not an array. 336 | * 337 | * @param string $type The operation type. 338 | * @param mixed $data The array to check. 339 | * @param string $param The dot notation or filepath. 340 | * 341 | * @throws NoIterableFileException if the file isn't a JSON array. 342 | * @throws NoIterableElementException if $dot isn't an array location. 343 | */ 344 | protected function failIfNotArray(string $type, mixed $data, string $param): void 345 | { 346 | if (is_array($data)) { 347 | return; 348 | } 349 | 350 | if (file_exists($param)) { 351 | throw new NoIterableFileException($param, $type); 352 | } 353 | 354 | throw new NoIterableElementException($param, $type); 355 | } 356 | } 357 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP JSON library 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/josantonius/Json/v/stable)](https://packagist.org/packages/josantonius/json) 4 | [![License](https://poser.pugx.org/josantonius/json/license)](LICENSE) 5 | [![Total Downloads](https://poser.pugx.org/josantonius/json/downloads)](https://packagist.org/packages/josantonius/json) 6 | [![CI](https://github.com/josantonius/php-json/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/josantonius/php-json/actions/workflows/ci.yml) 7 | [![CodeCov](https://codecov.io/gh/josantonius/php-json/branch/main/graph/badge.svg)](https://codecov.io/gh/josantonius/php-json) 8 | [![PSR1](https://img.shields.io/badge/PSR-1-f57046.svg)](https://www.php-fig.org/psr/psr-1/) 9 | [![PSR4](https://img.shields.io/badge/PSR-4-9b59b6.svg)](https://www.php-fig.org/psr/psr-4/) 10 | [![PSR12](https://img.shields.io/badge/PSR-12-1abc9c.svg)](https://www.php-fig.org/psr/psr-12/) 11 | 12 | PHP simple library for managing JSON files. 13 | 14 | --- 15 | 16 | - [Requirements](#requirements) 17 | - [Installation](#installation) 18 | - [Available Classes](#available-classes) 19 | - [Json Class](#json-class) 20 | - [Exceptions Used](#exceptions-used) 21 | - [Usage](#usage) 22 | - [Tests](#tests) 23 | - [TODO](#todo) 24 | - [Changelog](#changelog) 25 | - [Contribution](#contribution) 26 | - [Sponsor](#sponsor) 27 | - [License](#license) 28 | 29 | --- 30 | 31 | ## Requirements 32 | 33 | - Operating System: Linux. 34 | 35 | - PHP versions: 8.1 | 8.2. 36 | 37 | ## Installation 38 | 39 | The preferred way to install this extension is through [Composer](http://getcomposer.org/download/). 40 | 41 | To install **PHP JSON library**, simply: 42 | 43 | ```console 44 | composer require josantonius/json 45 | ``` 46 | 47 | The previous command will only install the necessary files, 48 | if you prefer to **download the full source code** use: 49 | 50 | ```console 51 | composer require josantonius/json --prefer-source 52 | ``` 53 | 54 | You can also **clone the complete repository** with Git: 55 | 56 | ```console 57 | git clone https://github.com/josantonius/php-json.git 58 | ``` 59 | 60 | ## Available Classes 61 | 62 | ### Json Class 63 | 64 | `Josantonius\Json\Json` 65 | 66 | Create object referencing the JSON file: 67 | 68 | ```php 69 | /** 70 | * @param string $filepath The path to the JSON file to be handled. 71 | */ 72 | public function __construct(public readonly string $filepath) 73 | { 74 | } 75 | ``` 76 | 77 | Get the path to the JSON file: 78 | 79 | ```php 80 | public readonly string $filepath; 81 | ``` 82 | 83 | Check if the JSON file has already been created: 84 | 85 | ```php 86 | /** 87 | * @return bool True if the file exists at the specified filepath, false otherwise. 88 | */ 89 | public function exists(): bool; 90 | ``` 91 | 92 | Get the contents of the JSON file: 93 | 94 | ```php 95 | /** 96 | * @param bool $asObject If true and the value is an array, it is returned as an object. 97 | * 98 | * @throws GetFileException 99 | * @throws JsonErrorException 100 | * 101 | * @return mixed the contents of the JSON file. 102 | */ 103 | public function get(bool $asObject = false): mixed; 104 | ``` 105 | 106 | Set the contents of a JSON or a key within the file: 107 | 108 | ```php 109 | /** 110 | * @param mixed $content The data that will be written to the file or a key within the file. 111 | * @param string $dot The dot notation representing the key to be modified within the file. 112 | * 113 | * @throws GetFileException 114 | * @throws JsonErrorException 115 | * @throws CreateFileException 116 | * @throws CreateDirectoryException 117 | * @throws NoIterableElementException 118 | * 119 | * @return mixed the content of the JSON file after the set operation. 120 | */ 121 | public function set(mixed $content = [], string $dot = null): array|bool|int|null|string; 122 | ``` 123 | 124 | Merge the provided data with the contents of a JSON file or a key within the file: 125 | 126 | ```php 127 | /** 128 | * @param mixed $content The data that will be written to the file or a key within the file. 129 | * @param string $dot The dot notation representing the key to be modified within the file. 130 | * 131 | * @throws GetFileException 132 | * @throws JsonErrorException 133 | * @throws NoIterableFileException 134 | * @throws NoIterableElementException 135 | * 136 | * @return mixed the content of the JSON file after the merge operation. 137 | */ 138 | public function merge(array|object $content, string $dot = null): array; 139 | ``` 140 | 141 | Remove and get the last element of a JSON file or a key within the file: 142 | 143 | ```php 144 | /** 145 | * @param string $dot The dot notation representing the key to be modified within the file. 146 | * 147 | * @throws GetFileException 148 | * @throws JsonErrorException 149 | * @throws NoIterableFileException 150 | * @throws NoIterableElementException 151 | * 152 | * @return mixed|null the last value of JSON file, or null if array is empty. 153 | */ 154 | public function pop(string $dot = null): mixed; 155 | ``` 156 | 157 | Add the provided data to the end of the contents of a JSON file or a key within the file: 158 | 159 | ```php 160 | /** 161 | * @param mixed $content The data that will be written to the file or a key within the file. 162 | * @param string $dot The dot notation representing the key to be modified within the file. 163 | * 164 | * @throws GetFileException 165 | * @throws JsonErrorException 166 | * @throws NoIterableFileException 167 | * @throws NoIterableElementException 168 | * 169 | * @return mixed the content of the JSON file after the push operation. 170 | */ 171 | public function push(mixed $content, string $dot = null): array; 172 | ``` 173 | 174 | Remove and get the first element of a JSON file or a key within the file: 175 | 176 | ```php 177 | /** 178 | * @param string $dot The dot notation representing the key to be modified within the file. 179 | * 180 | * @throws GetFileException 181 | * @throws JsonErrorException 182 | * @throws NoIterableFileException 183 | * @throws NoIterableElementException 184 | * 185 | * @return mixed|null the shifted value, or null if array is empty. 186 | */ 187 | public function shift(string $dot = null): mixed(mixed $content, string $dot = null): array; 188 | ``` 189 | 190 | Remove a key and its value from the contents of a JSON file: 191 | 192 | ```php 193 | /** 194 | * @param string $dot The dot notation representing the key to be modified within the file. 195 | * @param bool $reindexed If true, the array will be re-indexed. 196 | * 197 | * @throws GetFileException 198 | * @throws JsonErrorException 199 | * @throws NoIterableFileException 200 | * 201 | * @return array the content of the JSON file after the unset operation. 202 | */ 203 | public function unset(string $dot, bool $reindexed = false): array; 204 | ``` 205 | 206 | Add the provided data to the beginning of the contents of a JSON file or a key within the file: 207 | 208 | ```php 209 | /** 210 | * @param mixed $content The data that will be written to the file or a key within the file. 211 | * @param string $dot The dot notation representing the key to be modified within the file. 212 | * 213 | * @throws GetFileException 214 | * @throws JsonErrorException 215 | * @throws NoIterableFileException 216 | * @throws NoIterableElementException 217 | * 218 | * @return mixed the content of the JSON file after the unshift operation. 219 | */ 220 | public function unshift(mixed $content, string $dot = null): mixed; 221 | ``` 222 | 223 | ## Exceptions Used 224 | 225 | ```php 226 | use Josantonius\Json\Exceptions\GetFileException; // if file reading failed 227 | use Josantonius\Json\Exceptions\CreateFileException; // if file creation failed 228 | use Josantonius\Json\Exceptions\JsonErrorException; // if the file contains invalid JSON 229 | use Josantonius\Json\Exceptions\NoIterableFileException; // if the file isn't a JSON array 230 | use Josantonius\Json\Exceptions\CreateDirectoryException; // if directory creation failed 231 | use Josantonius\Json\Exceptions\NoIterableElementException; // if $dot isn't an array location 232 | ``` 233 | 234 | ## Usage 235 | 236 | Example of use for this library: 237 | 238 | ### Get the path of the JSON file 239 | 240 | ```php 241 | use Josantonius\Json\Json; 242 | 243 | $json = new Json('file.json'); 244 | 245 | $json->filepath; // 'file.json' 246 | ``` 247 | 248 | ### Check whether a local file exists 249 | 250 | ```php 251 | use Josantonius\Json\Json; 252 | 253 | $json = new Json('file.json'); 254 | 255 | $json->exists(); // bool 256 | ``` 257 | 258 | ### Get the JSON file contents as array 259 | 260 | **`file.json`** 261 | 262 | ```json 263 | { 264 | "foo": "bar" 265 | } 266 | ``` 267 | 268 | **`index.php`** 269 | 270 | ```php 271 | use Josantonius\Json\Json; 272 | 273 | $json = new Json('file.json'); 274 | 275 | $json->get(); // ['foo' => 'bar'] 276 | ``` 277 | 278 | ### Get the JSON file contents as object 279 | 280 | **`file.json`** 281 | 282 | ```json 283 | { 284 | "foo": "bar" 285 | } 286 | ``` 287 | 288 | **`index.php`** 289 | 290 | ```php 291 | use Josantonius\Json\Json; 292 | 293 | $json = new Json('file.json'); 294 | 295 | $json->get(asObject: true); // object(stdClass) { ["foo"] => string(3) "bar" } 296 | ``` 297 | 298 | ### Set an empty array in the JSON file contents 299 | 300 | **`index.php`** 301 | 302 | ```php 303 | use Josantonius\Json\Json; 304 | 305 | $json = new Json('file.json'); 306 | 307 | $json->set(); 308 | ``` 309 | 310 | **`file.json`** 311 | 312 | ```json 313 | [] 314 | ``` 315 | 316 | ### Set the contents of a JSON file 317 | 318 | **`index.php`** 319 | 320 | ```php 321 | use Josantonius\Json\Json; 322 | 323 | $json = new Json('file.json'); 324 | 325 | $json->set(['foo' => 'bar']); 326 | ``` 327 | 328 | **`file.json`** 329 | 330 | ```json 331 | { 332 | "foo": "bar" 333 | } 334 | ``` 335 | 336 | ### Set the contents of a key within the JSON file using dot notation 337 | 338 | **`file.json`** 339 | 340 | ```json 341 | { 342 | "foo": { 343 | "bar": [] 344 | } 345 | } 346 | ``` 347 | 348 | **`index.php`** 349 | 350 | ```php 351 | use Josantonius\Json\Json; 352 | 353 | $json = new Json('file.json'); 354 | 355 | $json->set('baz', 'foo.bar.0'); 356 | ``` 357 | 358 | **`file.json`** 359 | 360 | ```json 361 | { 362 | "foo": { 363 | "bar": [ 364 | "baz" 365 | ] 366 | } 367 | } 368 | ``` 369 | 370 | ### Merge the provided data with the contents of the JSON file 371 | 372 | **`file.json`** 373 | 374 | ```json 375 | { 376 | "foo": "bar" 377 | } 378 | ``` 379 | 380 | **`index.php`** 381 | 382 | ```php 383 | use Josantonius\Json\Json; 384 | 385 | $json = new Json('file.json'); 386 | 387 | $json->merge(['bar' => 'foo']); 388 | ``` 389 | 390 | **`file.json`** 391 | 392 | ```json 393 | { 394 | "foo": "bar", 395 | "bar": "foo" 396 | } 397 | ``` 398 | 399 | ### Merge the provided data with the contents of a key within the file using dot notation 400 | 401 | **`file.json`** 402 | 403 | ```json 404 | { 405 | "foo": [ 406 | { 407 | "bar": "baz" 408 | } 409 | ] 410 | } 411 | ``` 412 | 413 | **`index.php`** 414 | 415 | ```php 416 | use Josantonius\Json\Json; 417 | 418 | $json = new Json('file.json'); 419 | 420 | $json->merge(['baz' => 'bar'], 'foo.0'); 421 | ``` 422 | 423 | **`file.json`** 424 | 425 | ```json 426 | { 427 | "foo": [ 428 | { 429 | "bar": "baz", 430 | "baz": "bar" 431 | } 432 | ] 433 | } 434 | ``` 435 | 436 | ### Remove and get the last element of a JSON file 437 | 438 | **`file.json`** 439 | 440 | ```json 441 | [ 442 | 1, 443 | 2, 444 | 3 445 | ] 446 | ``` 447 | 448 | **`index.php`** 449 | 450 | ```php 451 | use Josantonius\Json\Json; 452 | 453 | $json = new Json('file.json'); 454 | 455 | $json->pop(); // 3 456 | ``` 457 | 458 | **`file.json`** 459 | 460 | ```json 461 | [ 462 | 1, 463 | 2 464 | ] 465 | ``` 466 | 467 | ### Remove and get the last element of a key within the file using dot notation 468 | 469 | **`file.json`** 470 | 471 | ```json 472 | { 473 | "foo": [ 474 | 1, 475 | 2, 476 | 3 477 | ] 478 | } 479 | ``` 480 | 481 | **`index.php`** 482 | 483 | ```php 484 | use Josantonius\Json\Json; 485 | 486 | $json = new Json('file.json'); 487 | 488 | $json->pop(); // 3 489 | ``` 490 | 491 | **`file.json`** 492 | 493 | ```json 494 | { 495 | "foo": [ 496 | 1, 497 | 2 498 | ] 499 | } 500 | ``` 501 | 502 | ### Add the provided data to the end of the contents of a JSON file 503 | 504 | **`file.json`** 505 | 506 | ```json 507 | [ 508 | { 509 | "name": "foo" 510 | } 511 | ] 512 | ``` 513 | 514 | **`index.php`** 515 | 516 | ```php 517 | use Josantonius\Json\Json; 518 | 519 | $json = new Json('file.json'); 520 | 521 | $json->push(['name' => 'bar']); 522 | ``` 523 | 524 | **`file.json`** 525 | 526 | ```json 527 | [ 528 | { 529 | "name": "foo" 530 | }, 531 | { 532 | "name": "bar" 533 | } 534 | ] 535 | ``` 536 | 537 | ### Add provided data to the end of the contents of a key within the file using dot notation 538 | 539 | **`file.json`** 540 | 541 | ```json 542 | { 543 | "foo": { 544 | "bar": [ 545 | [] 546 | ] 547 | } 548 | } 549 | ``` 550 | 551 | **`index.php`** 552 | 553 | ```php 554 | use Josantonius\Json\Json; 555 | 556 | $json = new Json('file.json'); 557 | 558 | $json->push('baz', 'foo.bar.0'); 559 | ``` 560 | 561 | **`file.json`** 562 | 563 | ```json 564 | { 565 | "foo": { 566 | "bar": [ 567 | [ 568 | "baz" 569 | ] 570 | ] 571 | } 572 | } 573 | ``` 574 | 575 | ### Remove and get the first element of the contents of a JSON file 576 | 577 | **`file.json`** 578 | 579 | ```json 580 | [ 581 | 1, 582 | 2, 583 | 3 584 | ] 585 | ``` 586 | 587 | **`index.php`** 588 | 589 | ```php 590 | use Josantonius\Json\Json; 591 | 592 | $json = new Json('file.json'); 593 | 594 | $json->shift(); // 1 595 | ``` 596 | 597 | **`file.json`** 598 | 599 | ```json 600 | [ 601 | 2, 602 | 3 603 | ] 604 | ``` 605 | 606 | ### Remove and get the first item of the contents of a key within the file using dot notation 607 | 608 | **`file.json`** 609 | 610 | ```json 611 | { 612 | "foo": { 613 | "bar": [ 614 | [ 615 | 1 616 | ] 617 | ] 618 | } 619 | } 620 | ``` 621 | 622 | **`index.php`** 623 | 624 | ```php 625 | use Josantonius\Json\Json; 626 | 627 | $json = new Json('file.json'); 628 | 629 | $json->shift('foo.bar.0'); // 1 630 | ``` 631 | 632 | **`file.json`** 633 | 634 | ```json 635 | { 636 | "foo": { 637 | "bar": [ 638 | [] 639 | ] 640 | } 641 | } 642 | ``` 643 | 644 | ### Remove a string key and its value from the contents of a JSON file 645 | 646 | **`file.json`** 647 | 648 | ```json 649 | { 650 | "foo": { 651 | "bar": [ 652 | [] 653 | ] 654 | } 655 | } 656 | ``` 657 | 658 | **`index.php`** 659 | 660 | ```php 661 | use Josantonius\Json\Json; 662 | 663 | $json = new Json('file.json'); 664 | 665 | $json->unset('foo.bar'); 666 | ``` 667 | 668 | **`file.json`** 669 | 670 | ```json 671 | { 672 | "foo": [] 673 | } 674 | ``` 675 | 676 | ### Remove a numeric key and its value from the contents of a JSON file 677 | 678 | **`file.json`** 679 | 680 | ```json 681 | [ 682 | 1, 683 | 2, 684 | 3 685 | ] 686 | ``` 687 | 688 | **`index.php`** 689 | 690 | ```php 691 | use Josantonius\Json\Json; 692 | 693 | $json = new Json('file.json'); 694 | 695 | $json->unset('1'); 696 | ``` 697 | 698 | **`file.json`** 699 | 700 | ```json 701 | { 702 | "0": 1, 703 | "2": 3 704 | } 705 | ``` 706 | 707 | ### Remove a numeric key and its value from the contents of a JSON file and re-index it 708 | 709 | **`file.json`** 710 | 711 | ```json 712 | [ 713 | 1, 714 | 2, 715 | 3 716 | ] 717 | ``` 718 | 719 | **`index.php`** 720 | 721 | ```php 722 | use Josantonius\Json\Json; 723 | 724 | $json = new Json('file.json'); 725 | 726 | $json->unset('1', reindexed: true); 727 | ``` 728 | 729 | **`file.json`** 730 | 731 | ```json 732 | [ 733 | 1, 734 | 3 735 | ] 736 | ``` 737 | 738 | ### Add the provided data to the beginning of the contents of a JSON file 739 | 740 | **`file.json`** 741 | 742 | ```json 743 | [ 744 | 1, 745 | 2, 746 | 3 747 | ] 748 | ``` 749 | 750 | **`index.php`** 751 | 752 | ```php 753 | use Josantonius\Json\Json; 754 | 755 | $json = new Json('file.json'); 756 | 757 | $json->unshift(0); 758 | ``` 759 | 760 | **`file.json`** 761 | 762 | ```json 763 | [ 764 | 0, 765 | 1, 766 | 2, 767 | 3 768 | ] 769 | ``` 770 | 771 | ### Add the provided data to the beginning of the contents of a key within the file using dot 772 | 773 | **`file.json`** 774 | 775 | ```json 776 | { 777 | "foo": { 778 | "bar": [ 779 | [ 780 | 1 781 | ] 782 | ] 783 | } 784 | } 785 | ``` 786 | 787 | **`index.php`** 788 | 789 | ```php 790 | use Josantonius\Json\Json; 791 | 792 | $json = new Json('file.json'); 793 | 794 | $json->unshift(0, 'foo.bar.0'); 795 | ``` 796 | 797 | **`file.json`** 798 | 799 | ```json 800 | { 801 | "foo": { 802 | "bar": [ 803 | [ 804 | 0, 805 | 1 806 | ] 807 | ] 808 | } 809 | } 810 | ``` 811 | 812 | ## Tests 813 | 814 | To run [tests](tests) you just need [composer](http://getcomposer.org/download/) 815 | and to execute the following: 816 | 817 | ```console 818 | git clone https://github.com/josantonius/php-json.git 819 | ``` 820 | 821 | ```console 822 | cd php-json 823 | ``` 824 | 825 | ```console 826 | composer install 827 | ``` 828 | 829 | Run unit tests with [PHPUnit](https://phpunit.de/): 830 | 831 | ```console 832 | composer phpunit 833 | ``` 834 | 835 | Run code standard tests with [PHPCS](https://github.com/squizlabs/PHP_CodeSniffer): 836 | 837 | ```console 838 | composer phpcs 839 | ``` 840 | 841 | Run [PHP Mess Detector](https://phpmd.org/) tests to detect inconsistencies in code style: 842 | 843 | ```console 844 | composer phpmd 845 | ``` 846 | 847 | Run all previous tests: 848 | 849 | ```console 850 | composer tests 851 | ``` 852 | 853 | ## TODO 854 | 855 | - [ ] Add new feature 856 | - [ ] Improve tests 857 | - [ ] Improve documentation 858 | - [ ] Improve English translation in the README file 859 | - [ ] Refactor code for disabled code style rules (see phpmd.xml and phpcs.xml) 860 | 861 | ## Changelog 862 | 863 | Detailed changes for each release are documented in the 864 | [release notes](https://github.com/josantonius/php-json/releases). 865 | 866 | ## Contribution 867 | 868 | Please make sure to read the [Contributing Guide](.github/CONTRIBUTING.md), before making a pull 869 | request, start a discussion or report a issue. 870 | 871 | Thanks to all [contributors](https://github.com/josantonius/php-json/graphs/contributors)! :heart: 872 | 873 | ## Sponsor 874 | 875 | If this project helps you to reduce your development time, 876 | [you can sponsor me](https://github.com/josantonius#sponsor) to support my open source work :blush: 877 | 878 | ## License 879 | 880 | This repository is licensed under the [MIT License](LICENSE). 881 | 882 | Copyright © 2016-present, [Josantonius](https://github.com/josantonius#contact) 883 | --------------------------------------------------------------------------------