maaaarcel / devalue-php
一个用于字符串化和解析复杂数据的库。灵感来源于devalue JavaScript库。
1.0.2
2023-02-11 23:49 UTC
Requires
- php: ^8.1
Requires (Dev)
- phpbench/phpbench: ^1.2.7
- phpunit/phpunit: ^9.5.28
This package is auto-updated.
Last update: 2024-09-12 03:08:15 UTC
README
这是由devalue(一个用于字符串化和解析过于复杂的JSON数据的JavaScript库)的PHP端口。请查看原始仓库以了解所有功能。
解析和字符串化逻辑的所有荣誉归功于devalue库的创建者和贡献者。这个实现中的逻辑基本上是相同的,但为了提高PHP的性能做了一些轻微的修改。
安装
使用composer安装
composer require maaaarcel/devalue-php
用法
Devalue
类具有stringify
、parse
和unflatten
方法,用于后端进行字符串化和解析。
use Maaaarcel\DevaluePhp\Devalue; use Maaaarcel\DevaluePhp\JavaScript\JsBigInt; use Maaaarcel\DevaluePhp\JavaScript\JsNumberObject; use Maaaarcel\DevaluePhp\JavaScript\JsRegExp; use DateTime; $obj = new stdClass(); $obj->self = $obj; $data = [ 'recursiveObject' => $obj, 'regex' => new JsRegExp('.+', 'g'), 'date' => new DateTime('2023-01-16'), 'autoConverted' => INF, 'undefined' => JsValue::Undefined, 'normalNumber' => 1, 'array' => [new JsBigInt(1), new JsNumberObject(2)] ]; $dataStr = Devalue::stringify($data); // => '[{"recursiveObject":1,"regex":2,"date":3,"autoConverted":-4,"undefined":-1,"normalNumber":4,"array":5},{"self":1},["RegExp",".+","g"],["Date","2023-01-16T00:00:00.000Z"],1,[6,7],["BigInt","1"],["Object",2]]' $parsedData = Devalue::parse($dataStr); // => object(stdClass)#507 (7) { // ["recursiveObject"]=> // object(stdClass)#505 (1) { // ["self"]=> // *RECURSION* // } // ["regex"]=> // object(Maaaarcel\DevaluePhp\JavaScript\JsRegExp)#506 (2) { // ["source":"Maaaarcel\DevaluePhp\JavaScript\JsRegExp":private]=> // string(2) ".+" // ["flags":"Maaaarcel\DevaluePhp\JavaScript\JsRegExp":private]=> // string(1) "g" // } // ["date"]=> // object(DateTime)#504 (3) { // ["date"]=> // string(26) "2023-01-16 00:00:00.000000" // ["timezone_type"]=> // int(2) // ["timezone"]=> // string(1) "Z" // } // ["autoConverted"]=> // enum(Maaaarcel\DevaluePhp\JavaScript\JsValue::PositiveInfinity) // ["undefined"]=> // enum(Maaaarcel\DevaluePhp\JavaScript\JsValue::Undefined) // ["normalNumber"]=> // int(1) // ["array"]=> // object(ArrayObject)#503 (1) { // ["storage":"ArrayObject":private]=> // array(2) { // [0]=> // object(Maaaarcel\DevaluePhp\JavaScript\JsBigInt)#501 (1) { // ["value":"Maaaarcel\DevaluePhp\JavaScript\JsBigInt":private]=> // int(1) // } // [1]=> // object(Maaaarcel\DevaluePhp\JavaScript\JsNumberObject)#500 (1) { // ["value":"Maaaarcel\DevaluePhp\JavaScript\JsNumberObject":private]=> // int(2) // } // } // } // } // if your devalue payload was inside a normal JSON string, you can use the value from json_decode with the `unflatten` // method like so: $json = '{ "type": "data", "data": [{...devalue data...}] }'; $payload = json_decode($json); $data = Devalue::unflatten($payload->data); // You can create custom types to transfer common objects. Custom types must implement the `DevalueSerializable` interface use Maaaarcel\DevaluePhp\DevalueSerializable; class CustomType implements DevalueSerializable { public function __construct( public readonly string $field1 = '', public readonly string $field2 = '' ) { } // specify the name of the type (used for parsing in the frontend library) static function devalueType(): string { return 'CustomType'; } // create a class instance from the serialized data static function devalueParse(array $serialized): static { return new self($serialized['field1'], $serialized['field2']); } // serialize the data function devalueSerialize(): array { return [ 'field1' => $this->field1, 'field2' => $this->field2 ]; } } $stringifiedCustomType = Devalue::stringify(new CustomType('foo', 'bar')); // => '[["CustomType",1],{"field1":2,"field2":3},"foo","bar"]' // To parse custom types, you can either specify your custom types globally, or individually for every parse. // register type globally Devalue::registerCustomTypes([CustomType::class]); $parsedCustomType = Devalue::parse($stringifiedCustomType, [CustomType::class]); // register type only for this parse // => class CustomType#552 (2) { // public readonly string $field1 => // string(3) "foo" // public readonly string $field2 => // string(3) "bar" // }
Devalue::stringify
可以处理以下数据类型
\Maaaarcel\DevaluePhp\JavaScript\JsBooleanObject
\Maaaarcel\DevaluePhp\JavaScript\JsNumberObject
\Maaaarcel\DevaluePhp\JavaScript\JsStringObject
\Maaaarcel\DevaluePhp\JavaScript\JsBigInt
\Maaaarcel\DevaluePhp\JavaScript\JsMap
\Maaaarcel\DevaluePhp\JavaScript\JsSet
\Maaaarcel\DevaluePhp\JavaScript\JsRegExp
int
(如果数字大于9007199254740991
,则自动转换为BigInt
)float
string
bool
null
NAN
(转换为NaN
)INF
(转换为Infinity
/-Infinity
)\DateTimeInterface
(转换为Date()
)\JsonSerializable
(转换为JS对象)\stdClass
(转换为JS对象)\ArrayObject
(转换为JS数组)[1, 2, 3] (list)
(转换为JS数组)['a' => 1, 'b' => 2, 'c' => 3] (assoc array)
(转换为JS对象)
Devalue::parse
和Devalue::unflatten
方法将某些JavaScript值转换为对象/枚举值,以更准确地表示数据。这些对象/枚举值也可以在调用Devalue::stringify
时用于传递这些JavaScript值。
以下是一个转换列表(左:JavaScript值,右:PHP值)
objects
:\stdClass()
arrays
:\ArrayObject()
Date()
:\DateTime()
BigInt()
:\Maaaarcel\DevaluePhp\JavaScript\JsBigInt()
Boolean()
:\Maaaarcel\DevaluePhp\JavaScript\JsBooleanObject()
Number()
:\Maaaarcel\DevaluePhp\JavaScript\JsNumberObject()
String()
:\Maaaarcel\DevaluePhp\JavaScript\JsStringObject()
RegExp()
:\Maaaarcel\DevaluePhp\JavaScript\JsRegExp()
Map()
:\Maaaarcel\DevaluePhp\JavaScript\JsMap()
Set()
:\Maaaarcel\DevaluePhp\JavaScript\JsSet()
undefined
:\Maaaarcel\DevaluePhp\JavaScript\JsValue::Undefined
NaN
:\Maaaarcel\DevaluePhp\JavaScript\JsValue::Nan
-0
:\Maaaarcel\DevaluePhp\JavaScript\JsValue::NegativeZero
Infinity
:\Maaaarcel\DevaluePhp\JavaScript\JsValue::PositiveInfinity
-Infinity
:\Maaaarcel\DevaluePhp\JavaScript\JsValue::NegativeInfinity
在创建字符串之前,Stringify会转换一些特定的PHP值,以实现更好的兼容性和可用性
要在您的前端代码中消耗数据,您必须使用原始的devalue库。
性能
请查看当前提交的github action性能结果。基准测试使用phpbench运行