1
0
mirror of https://github.com/flextype/flextype.git synced 2025-08-06 21:26:48 +02:00

feat(serializers): add json5 serializer

This commit is contained in:
Awilum
2022-04-15 15:46:21 +03:00
parent 4f4e78c1bb
commit f10bfec0f8
5 changed files with 160 additions and 1 deletions

View File

@@ -60,7 +60,8 @@
"filp/whoops": "^2.14.5",
"symfony/console": "^5.4.3",
"symfony/var-exporter": "^5.4.3",
"thermage/thermage": "^0.19.0"
"thermage/thermage": "^0.19.0",
"colinodell/json5": "^2.2"
},
"suggest": {
"ext-zend-opcache": "Recommended for better performance",

View File

@@ -0,0 +1,116 @@
<?php
declare(strict_types=1);
/**
* Flextype - Hybrid Content Management System with the freedom of a headless CMS
* and with the full functionality of a traditional CMS!
*
* Copyright (c) Sergey Romanenko (https://awilum.github.io)
*
* Licensed under The MIT License.
*
* For full copyright and license information, please see the LICENSE
* Redistributions of files must retain the above copyright notice.
*/
namespace Flextype\Serializers;
use RuntimeException;
use function cache;
use function defined;
use function json_decode;
use function json_encode;
use function json_last_error;
use function json_last_error_msg;
use function registry;
use function strings;
use const JSON_PRESERVE_ZERO_FRACTION;
use const JSON_PRETTY_PRINT;
use const JSON_UNESCAPED_SLASHES;
use const JSON_UNESCAPED_UNICODE;
class Json5
{
public const FORCE_ARRAY = 0b0001;
public const PRETTY = 0b0010;
public const ESCAPE_UNICODE = 0b0100;
/**
* Returns the JSON5 representation of a value.
*
* @param mixed $input The PHP value.
*
* @return mixed A JSON5 string representing the original PHP value.
*/
public function encode($input)
{
$options = registry()->get('flextype.settings.serializers.json5.encode.options');
$depth = registry()->get('flextype.settings.serializers.json5.encode.depth');
$options = ($options & self::ESCAPE_UNICODE ? 0 : JSON_UNESCAPED_UNICODE)
| JSON_UNESCAPED_SLASHES
| ($options & self::PRETTY ? JSON_PRETTY_PRINT : 0)
| (defined('JSON_PRESERVE_ZERO_FRACTION') ? JSON_PRESERVE_ZERO_FRACTION : 0);
$json = json_encode($input, $options, $depth);
if ($error = json_last_error()) {
throw new RuntimeException(json_last_error_msg(), $error);
}
return $json;
}
/**
* Takes a JSON5 encoded string and converts it into a PHP variable.
*
* @param string $input A string containing JSON5.
*
* @return mixed The JSON5 converted to a PHP value.
*
* @throws RuntimeException If the JSON5 is not valid.
*/
public function decode(string $input)
{
$cache = registry()->get('flextype.settings.serializers.json5.decode.cache');
$assoc = registry()->get('flextype.settings.serializers.json5.decode.assoc');
$depth = registry()->get('flextype.settings.serializers.json5.decode.depth');
$flags = registry()->get('flextype.settings.serializers.json5.decode.flags');
$decode = static function (string $input, bool $assoc, int $depth, int $flags) {
return json5_decode($input, $assoc, $depth, $flags);;
};
if ($cache === true && registry()->get('flextype.settings.cache.enabled') === true) {
$key = $this->getCacheID($input);
if ($dataFromCache = cache()->get($key)) {
return $dataFromCache;
}
$data = $decode($input, $assoc, $depth, $flags);
cache()->set($key, $data);
return $data;
}
return $decode($input, $assoc, $depth, $flags);
}
/**
* Get Cache ID for JSON5.
*
* @param string $input Input.
*
* @return string Cache ID.
*
* @access public
*/
public function getCacheID(string $input): string
{
return strings('json5' . $input)->hash()->toString();
}
}

View File

@@ -30,6 +30,14 @@ class Serializers
return new Json();
}
/**
* Create a Json instance.
*/
public function json5(): Json5
{
return new Json5();
}
/**
* Create a Yaml instance.
*/

View File

@@ -433,6 +433,15 @@ serializers:
encode:
options: 0
depth: 512
json5:
decode:
cache: true
assoc: true
depth: 512
flags: 0
encode:
options: 0
depth: 512
yaml:
decode:
cache: true

View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
test('encode', function () {
$this->assertEquals('{"title":"Foo","content":"Bar"}',
serializers()->json5()
->encode(['title' => 'Foo',
'content' => 'Bar']));
});
test('decode', function () {
$this->assertEquals(['title' => 'Foo',
'content' => 'Bar'],
serializers()->json5()
->decode('{"title":"Foo","content":"Bar"}'));
});
test('get cache ID', function () {
$string = '{"title":"Foo","content":"Bar"}';
$cache_id = serializers()->json5()
->getCacheID($string);
$this->assertEquals(32, strlen($cache_id));
$this->assertNotEquals($string, $cache_id);
});