mirror of
https://github.com/EFTEC/Services_JSON.git
synced 2026-08-25 03:26:42 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f2892bc19 | |||
| 0753c8c54a | |||
| 7d957752be | |||
| b1a90af079 | |||
| 43246435ec |
@@ -20,7 +20,9 @@ While this version doesn't have a better performance than **json_encode()** and
|
|||||||
extension, but it has the next features:
|
extension, but it has the next features:
|
||||||
|
|
||||||
- [x] it doesn't require an extension. If you can't install ext-json, then you can use this version.
|
- [x] it doesn't require an extension. If you can't install ext-json, then you can use this version.
|
||||||
- [x] **it works with JSON with unquoted keys** (for example JavaScript notation)
|
- [x] **it works with JSON with unquoted keys** (for example JavaScript notation), {aaa:2,bbb:"hello"}
|
||||||
|
- [x] **it could also work with unquoted values** {"aaa":2,"bbb":hello}
|
||||||
|
- [x] **it could also work with unwrapped content** "aaa":2,"bbb":"hello" instead of {aaa:2,bbb:"hello"}
|
||||||
- [x] It is a simple .php file with no dependency.
|
- [x] It is a simple .php file with no dependency.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -69,7 +71,15 @@ var_dump(Services_JSON::decode($json)); // as stdclass
|
|||||||
var_dump(Services_JSON::decode($json,Services_JSON::GET_ARRAY)); // as array
|
var_dump(Services_JSON::decode($json,Services_JSON::GET_ARRAY)); // as array
|
||||||
```
|
```
|
||||||
|
|
||||||
It also works (with the flag Services_JSON::DECODE_FIX_ROOT) where the string misses [] and {} at the start of the code
|
#### Json unwrapped.
|
||||||
|
|
||||||
|
With the flag **Services_JSON::DECODE_FIX_ROOT**, it also works when the origin text misses [] and {} at the start of the code.
|
||||||
|
Note, this feature is not foolproof, for example "[1,2,3],[4,5,6]" will not wrap as "[[1,2,3],[4,5,6]]"
|
||||||
|
|
||||||
|
```
|
||||||
|
{"a":222,"b:"ccc"} # normal json
|
||||||
|
"a":222,"b:"ccc" # json without the root parenthesis.
|
||||||
|
```
|
||||||
|
|
||||||
```php
|
```php
|
||||||
Services_JSON::decode('1,2,3',Services_JSON::GET_ARRAY | Services_JSON::DECODE_FIX_ROOT); // returns [1,2,3]
|
Services_JSON::decode('1,2,3',Services_JSON::GET_ARRAY | Services_JSON::DECODE_FIX_ROOT); // returns [1,2,3]
|
||||||
@@ -79,6 +89,18 @@ Services_JSON::decode('"k1":"v1", k2:2',Services_JSON::GET_ARRAY | Services_JSON
|
|||||||
> Note: DECODE_FIX_ROOT flag detects if the near character is ":" or ",". If the closest character is ":", then it returns
|
> Note: DECODE_FIX_ROOT flag detects if the near character is ":" or ",". If the closest character is ":", then it returns
|
||||||
> an object, otherwise it returns a list. If there is none, then it returns a list.
|
> an object, otherwise it returns a list. If there is none, then it returns a list.
|
||||||
|
|
||||||
|
#### Json with unquoted values
|
||||||
|
|
||||||
|
With the flag **Services_JSON::DECODE_NO_QUOTE** it also works when the string values are not quoted.
|
||||||
|
|
||||||
|
>Note: invisible characters at the beginner and at the end (tabs, line carriages) will be trimmed.
|
||||||
|
|
||||||
|
```php
|
||||||
|
|
||||||
|
Services_JSON::decode('{"a":aaa,"b":bbbb,"c": aaaaa}'
|
||||||
|
, Services_JSON::GET_ARRAY | Services_JSON::DECODE_NO_QUOTE) // ['a'=>'aaa','b'=>'bbbb','c' => 'aaaaa']
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Encode
|
### Encode
|
||||||
@@ -94,10 +116,17 @@ var_dump(Services_JSON::encode($obj)); // encode an object
|
|||||||
|
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
* 2.5
|
||||||
|
* now allows "@" and "." for key values.
|
||||||
|
* 2.4
|
||||||
|
* update requirements to php 7.4
|
||||||
|
* added more type hinting (type validation)
|
||||||
|
* 2.3.2
|
||||||
|
* Added flag to decode() DECODE_NO_QUOTE
|
||||||
* 2.3.1
|
* 2.3.1
|
||||||
* deleted unused code
|
* deleted unused code
|
||||||
* fixed comments.
|
* fixed comments.
|
||||||
|
* 25% of the code has been refactored.
|
||||||
* 2.3
|
* 2.3
|
||||||
* Fixed a typo with a comment.
|
* Fixed a typo with a comment.
|
||||||
* added phpunit. The entire code is tested but special codification.
|
* added phpunit. The entire code is tested but special codification.
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2.5"
|
"php": ">=7.4"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-mbstring": "*"
|
"ext-mbstring": "*"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?php
|
<?php /** @noinspection ForgottenDebugOutputInspection */
|
||||||
|
|
||||||
use eftec\ServicesJson\Services_JSON;
|
use eftec\ServicesJson\Services_JSON;
|
||||||
include '../vendor/autoload.php';
|
include '../vendor/autoload.php';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?php
|
<?php /** @noinspection ForgottenDebugOutputInspection */
|
||||||
|
|
||||||
use eftec\ServicesJson\Services_JSON;
|
use eftec\ServicesJson\Services_JSON;
|
||||||
|
|
||||||
@@ -9,12 +9,27 @@ include '../vendor/autoload.php';
|
|||||||
|
|
||||||
$json='{hello:{a:2,b:3},world:[1,2,3,"aaa","bbbb"]}';
|
$json='{hello:{a:2,b:3},world:[1,2,3,"aaa","bbbb"]}';
|
||||||
|
|
||||||
|
echo "<h1>Original:</h1><pre>$json</pre><br>";
|
||||||
|
|
||||||
echo "Decode as stdclass:<br>";
|
echo "<h1>Decode as stdclass:</h1>";
|
||||||
echo "<pre>";
|
echo "<pre>";
|
||||||
var_dump(Services_JSON::decode($json));
|
var_dump(Services_JSON::decode($json));
|
||||||
echo "</pre>";
|
echo "</pre>";
|
||||||
echo "Decode as array:<br>";
|
echo "<h1>Decode as array:</h1>";
|
||||||
echo "<pre>";
|
echo "<pre>";
|
||||||
var_dump(Services_JSON::decode($json,Services_JSON::GET_ARRAY));
|
var_dump(Services_JSON::decode($json,Services_JSON::GET_ARRAY));
|
||||||
echo "</pre>";
|
echo "</pre>";
|
||||||
|
|
||||||
|
$json='hello.world:{a:2,b:3},hello@world:[1,2,3,"aaa","bbbb"]';
|
||||||
|
|
||||||
|
echo "<h1>Original (.@ and missing {} or [] in root):</h1><pre>$json</pre><br>";
|
||||||
|
|
||||||
|
echo "<h1>Decode as stdclass:</h1>";
|
||||||
|
echo "<pre>";
|
||||||
|
var_dump(Services_JSON::decode($json,Services_JSON::DECODE_FIX_ROOT));
|
||||||
|
echo "</pre>";
|
||||||
|
echo "<h1>Decode as array:</h1>";
|
||||||
|
echo "<pre>";
|
||||||
|
var_dump(Services_JSON::decode($json,Services_JSON::GET_ARRAY|Services_JSON::DECODE_FIX_ROOT));
|
||||||
|
echo "</pre>";
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?php
|
<?php /** @noinspection ForgottenDebugOutputInspection */
|
||||||
|
|
||||||
use eftec\ServicesJson\Services_JSON;
|
use eftec\ServicesJson\Services_JSON;
|
||||||
|
|
||||||
|
|||||||
+24
-16
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php /** @noinspection UnknownInspectionInspection */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @noinspection TypeUnsafeArraySearchInspection
|
* @noinspection TypeUnsafeArraySearchInspection
|
||||||
* @noinspection PhpComposerExtensionStubsInspection
|
* @noinspection PhpComposerExtensionStubsInspection
|
||||||
@@ -91,12 +92,13 @@ class Services_JSON
|
|||||||
public const USE_TO_JSON = 64;
|
public const USE_TO_JSON = 64;
|
||||||
/** @var int If the fix value is broken, then it adds [] or {} automatically */
|
/** @var int If the fix value is broken, then it adds [] or {} automatically */
|
||||||
public const DECODE_FIX_ROOT = 128;
|
public const DECODE_FIX_ROOT = 128;
|
||||||
|
public const DECODE_NO_QUOTE = 256;
|
||||||
|
|
||||||
protected static $use = 0;
|
protected static int $use = 0;
|
||||||
// private - cache the mbstring lookup results..
|
// private - cache the mbstring lookup results..
|
||||||
protected static $_mb_strlen = false;
|
protected static bool $_mb_strlen = false;
|
||||||
protected static $_mb_substr = false;
|
protected static bool $_mb_substr = false;
|
||||||
protected static $_mb_convert_encoding = false;
|
protected static bool $_mb_convert_encoding = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* constructs a new JSON instance. We force this library as static
|
* constructs a new JSON instance. We force this library as static
|
||||||
@@ -127,7 +129,7 @@ class Services_JSON
|
|||||||
* @return string UTF-8 character
|
* @return string UTF-8 character
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
protected static function utf162utf8($utf16): string
|
protected static function utf162utf8(string $utf16): string
|
||||||
{
|
{
|
||||||
if (self::$_mb_convert_encoding) {
|
if (self::$_mb_convert_encoding) {
|
||||||
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
|
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
|
||||||
@@ -161,7 +163,7 @@ class Services_JSON
|
|||||||
* @return string UTF-16 character
|
* @return string UTF-16 character
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
public static function utf82utf16($utf8): string
|
public static function utf82utf16(string $utf8): string
|
||||||
{
|
{
|
||||||
if (self::$_mb_convert_encoding) {
|
if (self::$_mb_convert_encoding) {
|
||||||
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
|
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
|
||||||
@@ -203,7 +205,7 @@ class Services_JSON
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* encodes an arbitrary variable into JSON format without JSON Header - warning - may allow XSS!!!!)
|
* encodes an arbitrary variable into JSON format without JSON Header - warning - may allow XSS!!!!
|
||||||
*
|
*
|
||||||
* @param mixed $var any number, boolean, string, array, or object to be encoded.
|
* @param mixed $var any number, boolean, string, array, or object to be encoded.
|
||||||
* see argument 1 to Services_JSON() above for array-parsing behavior.
|
* see argument 1 to Services_JSON() above for array-parsing behavior.
|
||||||
@@ -424,13 +426,13 @@ class Services_JSON
|
|||||||
* @return string JSON-formatted name-value pair, like '"name":value'
|
* @return string JSON-formatted name-value pair, like '"name":value'
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
protected static function name_value($name, $value)
|
protected static function name_value(string $name, $value)
|
||||||
{
|
{
|
||||||
$encoded_value = self::_encode($value);
|
$encoded_value = self::_encode($value);
|
||||||
if (self::isError($encoded_value)) {
|
if (self::isError($encoded_value)) {
|
||||||
return $encoded_value;
|
return $encoded_value;
|
||||||
}
|
}
|
||||||
return self::_encode((string)$name) . ':' . $encoded_value;
|
return self::_encode($name) . ':' . $encoded_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -441,7 +443,7 @@ class Services_JSON
|
|||||||
* @return string string value stripped of comments and whitespace
|
* @return string string value stripped of comments and whitespace
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
protected static function reduce_string($str): string
|
protected static function reduce_string(string $str): string
|
||||||
{
|
{
|
||||||
$str = preg_replace([// eliminate single line comments in '// ...' form
|
$str = preg_replace([// eliminate single line comments in '// ...' form
|
||||||
'#^\s*//(.+)$#m', // eliminate multi-line comments in '/* ... */' form, at start of string
|
'#^\s*//(.+)$#m', // eliminate multi-line comments in '/* ... */' form, at start of string
|
||||||
@@ -479,10 +481,13 @@ class Services_JSON
|
|||||||
* in ASCII or UTF-8 format!<br>
|
* in ASCII or UTF-8 format!<br>
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
public static function decode($str, int $use = 0)
|
public static function decode(string $str, int $use = 0)
|
||||||
{
|
{
|
||||||
if ($use & self::DECODE_FIX_ROOT) {
|
if ($use & self::DECODE_FIX_ROOT) {
|
||||||
$str = trim($str);
|
$str = trim($str);
|
||||||
|
if($str==="") {
|
||||||
|
throw new RuntimeException("no value to decode");
|
||||||
|
}
|
||||||
$firstChar = $str[0];
|
$firstChar = $str[0];
|
||||||
if ($firstChar !== '{' && $firstChar !== '[') {
|
if ($firstChar !== '{' && $firstChar !== '[') {
|
||||||
// fixing a malformed json-u, if the json-u doesn't start with { [ and ends with ] } then it wraps it
|
// fixing a malformed json-u, if the json-u doesn't start with { [ and ends with ] } then it wraps it
|
||||||
@@ -658,7 +663,7 @@ class Services_JSON
|
|||||||
} else {
|
} else {
|
||||||
$obj->$key = $val;
|
$obj->$key = $val;
|
||||||
}
|
}
|
||||||
} /** @noinspection NotOptimalRegularExpressionsInspection */ elseif (preg_match('/^\s*(\w+)\s*:/Ui', $slice, $parts)) {
|
} /** @noinspection NotOptimalRegularExpressionsInspection */ elseif (preg_match('/^\s*([a-z.@A-Z0-9_]+)\s*:/Ui', $slice, $parts)) {
|
||||||
// name:value pair, where name is unquoted
|
// name:value pair, where name is unquoted
|
||||||
$key = $parts[1];
|
$key = $parts[1];
|
||||||
$val = self::decode2(trim(substr($slice, strlen($parts[0])), ", \t\n\r\0\x0B"));
|
$val = self::decode2(trim(substr($slice, strlen($parts[0])), ", \t\n\r\0\x0B"));
|
||||||
@@ -709,6 +714,9 @@ class Services_JSON
|
|||||||
return $obj;
|
return $obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(self::$use & self::DECODE_NO_QUOTE) {
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -730,7 +738,7 @@ class Services_JSON
|
|||||||
* @param string $str
|
* @param string $str
|
||||||
* @return integer length
|
* @return integer length
|
||||||
*/
|
*/
|
||||||
protected static function strlen8($str): int
|
protected static function strlen8(string $str): int
|
||||||
{
|
{
|
||||||
if (self::$_mb_strlen) {
|
if (self::$_mb_strlen) {
|
||||||
return mb_strlen($str, "8bit");
|
return mb_strlen($str, "8bit");
|
||||||
@@ -742,10 +750,10 @@ class Services_JSON
|
|||||||
* Returns part of a string, interpreting $start and $length as number of bytes.
|
* Returns part of a string, interpreting $start and $length as number of bytes.
|
||||||
* @param string $string
|
* @param string $string
|
||||||
* @param integer $start start
|
* @param integer $start start
|
||||||
* @param integer $length length
|
* @param integer|bool $length length
|
||||||
* @return string length
|
* @return string length
|
||||||
*/
|
*/
|
||||||
protected static function substr8($string, $start, $length = false): string
|
protected static function substr8(string $string, int $start, $length = false): string
|
||||||
{
|
{
|
||||||
if ($length === false) {
|
if ($length === false) {
|
||||||
$length = self::strlen8($string) - $start;
|
$length = self::strlen8($string) - $start;
|
||||||
|
|||||||
@@ -32,6 +32,14 @@ final class FirstTest extends TestCase
|
|||||||
,Services_JSON::decode('"k1":"v1", k2:2',
|
,Services_JSON::decode('"k1":"v1", k2:2',
|
||||||
Services_JSON::GET_ARRAY | Services_JSON::DECODE_FIX_ROOT)
|
Services_JSON::GET_ARRAY | Services_JSON::DECODE_FIX_ROOT)
|
||||||
);
|
);
|
||||||
|
//
|
||||||
|
$this->assertEquals(
|
||||||
|
[ 'button1' =>["aaaa","bbb","cccc"],
|
||||||
|
'button2' =>["aaaa","bbb","cccc"],
|
||||||
|
'button3' =>["aaaa","bbb","cccc"],]
|
||||||
|
,Services_JSON::decode('{"button1":["aaaa","bbb","cccc"],"button2":["aaaa","bbb","cccc"],"button3":["aaaa","bbb","cccc"]}',
|
||||||
|
Services_JSON::GET_ARRAY | Services_JSON::DECODE_FIX_ROOT)
|
||||||
|
);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
[ 1,2,3]
|
[ 1,2,3]
|
||||||
,Services_JSON::decode('1,2,3',
|
,Services_JSON::decode('1,2,3',
|
||||||
@@ -47,6 +55,21 @@ final class FirstTest extends TestCase
|
|||||||
,Services_JSON::decode('a:1',
|
,Services_JSON::decode('a:1',
|
||||||
Services_JSON::GET_ARRAY | Services_JSON::DECODE_FIX_ROOT)
|
Services_JSON::GET_ARRAY | Services_JSON::DECODE_FIX_ROOT)
|
||||||
);
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
['a.b@c'=>1]
|
||||||
|
,Services_JSON::decode('a.b@c:1',
|
||||||
|
Services_JSON::GET_ARRAY | Services_JSON::DECODE_FIX_ROOT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
public function testsimple(): void
|
||||||
|
{
|
||||||
|
$this->assertEquals(
|
||||||
|
['a'=>'aaa','b'=>'bbbb','c' => 'aaaaa']
|
||||||
|
,Services_JSON::decode('a:aaa,b:bbbb,c: aaaaa',
|
||||||
|
Services_JSON::GET_ARRAY | Services_JSON::DECODE_FIX_ROOT | Services_JSON::DECODE_NO_QUOTE));
|
||||||
|
$this->assertEquals(
|
||||||
|
['a'=>'aaa','b'=>'bbbb','c' => 'aaaaa']
|
||||||
|
,Services_JSON::decode('{"a":aaa,"b":bbbb,"c": aaaaa}', Services_JSON::GET_ARRAY | Services_JSON::DECODE_NO_QUOTE));
|
||||||
}
|
}
|
||||||
public function testEncode(): void
|
public function testEncode(): void
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user