crossjoin / json
PHP 的 JSON 解码器和编码器,完全支持 Unicode,遵循 RFC 7159。除了 UTF-8 外,它还支持 UTF-16BE、UTF-16LE、UTF-32BE 和 UTF-32LE 编码。并且,根据 RFC 的建议,在解析 JSON 时也可以忽略字节顺序标记(BOM)。
Requires
- php: ^5.3.3 || ^7.0
- ext-json: *
Requires (Dev)
- php: ^5.3.3 || ^7.0
- ext-iconv: *
- ext-json: *
- phpunit/phpunit: ^4.8.23
Suggests
- ext-iconv: To support JSON in other encodings than UTF-8, either the iconv, intl (if PHP >= 5.5.0) or mbstring extension is required.
- ext-intl: To support JSON in other encodings than UTF-8, either the iconv, intl (if PHP >= 5.5.0) or mbstring extension is required.
- ext-mbstring: To support JSON in other encodings than UTF-8, either the iconv, intl (if PHP >= 5.5.0) or mbstring extension is required.
This package is not auto-updated.
Last update: 2020-02-07 07:38:56 UTC
README
介绍
此库提供了一个基于原生 PHP json_*
函数的 JSON 解码器和编码器,但具有完全的 Unicode 支持,遵循 RFC 7159。
原生 PHP 函数仅支持以 UTF-8 编码且不包含字节顺序标记(BOM)的 JSON 字符串。
此库封装了 PHP 函数,并允许您使用 RFC 允许的以下附加编码解码和编码 JSON 文件
- UTF-16BE
- UTF-16LE
- UTF-32BE
- UTF-32LE
默认情况下(可以禁用)它还忽略了解析时的字节顺序标记(BOM),正如 RFC 在 "互操作性方面的利益" 中建议的那样。
安装
您可以使用 Composer 安装此库。可以通过命令行界面...
$ composer install crossjoin/json
或者通过向您的 composer.json
文件添加以下要求
{
"require": {
"crossjoin/json": "^1.0.0"
}
}
要求
此库支持以下 PHP 版本(版本越新,JSON 支持越好)
- PHP >= 5.3.3
- PHP >= 7.0.0
- HHVM(使用版本 3.6.6 进行测试)
以下扩展之一是必需的,以支持与 UTF-8 不同的编码
- iconv
- mbstring
- intl(只能与 PHP >= 5.5.0 一起使用)
用法
解码
它是如何工作的?
首先检查 JSON 字符串是否有字节顺序标记和使用的编码。如果存在字节顺序标记,则从 JSON 字符串中删除它。如果使用除 UTF-8 以外的编码,则将 JSON 字符串的编码更改为 UTF-8。
最后,调用本机 json_decode()
函数以解码修改后的 JSON 字符串,因此结果依赖于本机 PHP 函数(并且可能在不同 PHP 版本之间有所不同)。
所有返回数据都编码为 UTF-8,因此您可以在 PHP 中使用它。
基本示例
使用 Crossjoin\Json
命名空间中提供的函数的基本示例
<?php // From PHP 5.6.0 you can also use namespaced functions to avoid the namespace // prefixes below. //use function \Crossjoin\Json\json_decode, \Crossjoin\Json\json_encode; //use function \Crossjoin\Json\json_last_error, \Crossjoin\Json\json_last_error_msg; // Decode example (same arguments as the native PHP function). // // Note: If an invalid type is used for one of the arguments, a // \Crossjoin\Json\Exception\InvalidArgumentException exception is thrown, // while the native PHP function may accept some of them. $data = \Crossjoin\Json\json_decode('{"key":"value"}'); //$data = \Crossjoin\Json\json_decode('{"key":"value"}', false,); //$data = \Crossjoin\Json\json_decode('{"key":"value"}', false, 512); //$data = \Crossjoin\Json\json_decode('{"key":"value"}', false, 512, \JSON_BIGINT_AS_STRING); // Also the functions json_last_error() and json_last_error_msg() can be used if (\Crossjoin\Json\json_last_error() !== \JSON_ERROR_NONE) { $errorMessage = \Crossjoin\Json\json_last_error_msg(); // Error handling // ... } else { // Do something with the data // ... }
扩展示例
前面的示例中的函数存在,以便于替换原生函数。内部函数使用类 \Crossjoin\Json\Decoder
,捕获所有异常(除了无效参数的异常)并返回与原生函数预期的相同结果。
如果您直接使用解码器类,您可以为如何处理字节顺序标记进行定义,并使用 json_last_error*
函数(尽管如此,仍然可以使用)来处理异常。
<?php use Crossjoin\Json\Decoder; use Crossjoin\Json\Exception\JsonException; use Crossjoin\Json\Exception\NativeJsonErrorException; // Get decoder instance with default options $decoder = new Decoder(); // Get decoder instance that accepts input with byte order mark (which is the default) //$decoder = new Decoder(true); // Get decoder instance that does not accept input with byte order mark //$decoder = new Decoder(false); // Byte order mark support may also be enabled/disabled after initialization //$decoder = new Decoder(); //$decoder->setIgnoreByteOrderMark(false); // Decode the data try { // Decode example (same arguments as the native PHP function). $data = $decoder->decode('{"key":"value"}', false, 512, \JSON_BIGINT_AS_STRING); // Do something with the data // ... } catch (NativeJsonErrorException $e) { // Catch native JSON errors, wrapped in an exception. The exception's // message and code are the same as returned by the native json_last_error* // functions (which can still be used) // Get native JSON error code, for example \JSON_ERROR_SYNTAX, // same as returned by json_last_error() $jsonError = $e->getCode(); // Get native JSON error message, same as returned by json_last_error_msg() $jsonErrorMessage = $e->getMessage(); // Error handling // ... } catch (JsonException $e) { // Catch misc errors, for example if JSON with an unsupported encoding was // used as input. // Error handling // ... }
编码
它是如何工作的?
数据使用本地 json_encode()
函数进行编码,因此结果 依赖于本地 PHP 函数(并且可能在不同 PHP 版本之间有所不同)。
输入必须编码为 UTF-8(或兼容的 ASCII 编码)。输出编码默认为 UTF-8,但可以设置为不同的 Unicode 编码。编码转换在将数据编码为 JSON 之后应用。
注意:输出不包含字节顺序标记,因为这不被 RFC 所允许。仅在解码 JSON 时允许接受。
基本示例
使用 Crossjoin\Json
命名空间中提供的函数的基本示例
<?php // From PHP 5.6.0 you can also use namespaced functions to avoid the namespace // prefixes below. //use function \Crossjoin\Json\json_decode, \Crossjoin\Json\json_encode; //use function \Crossjoin\Json\json_last_error, \Crossjoin\Json\json_last_error_msg; // Encode example (same arguments as the native PHP function) // // Note: If an invalid type is used for one of the arguments, a // \Crossjoin\Json\Exception\InvalidArgumentException exception is thrown, // while the native PHP function may accept some of them. $json = \Crossjoin\Json\json_encode(123); //$json = \Crossjoin\Json\json_encode(123, \JSON_NUMERIC_CHECK); //$json = \Crossjoin\Json\json_encode(123, \JSON_NUMERIC_CHECK, 512); // Also the functions json_last_error() and json_last_error_msg() can be used if (\Crossjoin\Json\json_last_error() !== \JSON_ERROR_NONE) { $errorMessage = \Crossjoin\Json\json_last_error_msg(); // Error handling // ... } else { // Do something with the JSON string // ... }
扩展示例
前面示例中的函数存在是为了方便替换本地函数。内部函数使用类 \Crossjoin\Json\Encoder
,捕获所有异常(除了无效参数的异常)并返回本地函数期望的相同结果。
如果您直接使用编码器类,您可以定义输出编码,并使用 json_last_error*
函数(仍然可以使用)来处理异常。
<?php use Crossjoin\Json\Encoder; use Crossjoin\Json\Exception\JsonException; use Crossjoin\Json\Exception\NativeJsonErrorException; // Get encoder instance with default options $encoder = new Encoder(); // Get encoder instance that uses UTF-8 encoding for the output (which is the default) //$encoder = new Encoder(Encoder::UTF8); // Get encoder instance that uses UTF-16BE encoding for the output //$encoder = new Encoder(Encoder::UTF16BE); // Get encoder instance that uses UTF-16LE encoding for the output //$encoder = new Encoder(Encoder::UTF16LE); // Get encoder instance that uses UTF-16BE encoding for the output //$encoder = new Encoder(Encoder::UTF32BE); // Get encoder instance that uses UTF-16LE encoding for the output //$encoder = new Encoder(Encoder::UTF32LE); // The encoding may also be changed after initialization //$encoder = new Encoder(); //$encoder->setEncoding(Encoder::UTF16BE); // Encode the data try { // Encode example (same arguments as the native PHP function). $json = $encoder->encode('my data', \JSON_NUMERIC_CHECK, 512); // Do something with the JSON string // ... } catch (NativeJsonErrorException $e) { // Catch native JSON errors, wrapped in an exception. The exception's // message and code are the same as returned by the native json_last_error* // functions (which can still be used) // Get native JSON error code, for example \JSON_ERROR_UNSUPPORTED_TYPE, // same as returned by json_last_error() $jsonError = $e->getCode(); // Get native JSON error message, same as returned by json_last_error_msg() $jsonErrorMessage = $e->getMessage(); // Error handling // ... } catch (JsonException $e) { // Catch misc errors, for example if invalid data was used as input. // Error handling // ... }
注意事项
处理无效参数
此库对给定参数的类型进行更严格的检查。
例如,本地 json_decode() 函数也接受整数或布尔值作为 JSON 字符串,这可能导致意外的结果。在这种情况下,此库将抛出 \Crossjoin\Json\Exception\InvalidArgumentException
异常。
后来 PHP 版本中添加的参数
本地 PHP 函数 json_decode
和 json_encode
的参数在不同 PHP 版本之间有所不同。较老的 PHP 版本不支持所有参数。当使用替换函数 \Crossjoin\Json\json_decode
和 \Crossjoin\Json\json_encode
时,这些参数可能被设置,但只有本地 PHP 版本支持它们时才会使用。
PHP < 5.5.0 中的错误消息
\Crossjoin\Json\json_last_error_msg()
函数返回原始错误消息,与本地 PHP 函数 json_last_error_msg()
返回的消息相同 - 除了 PHP < 5.5.0,因为在该版本中该函数不存在。在这种情况下,将返回默认错误消息。
PHP < 5.5.0 的不同结果
当您在 PHP < 5.5.0 中尝试编码无效类型时,例如资源,本地 PHP 函数 json_encode()
返回编码后的空值并触发错误。
此行为已被调整为 PHP 5.5.0 的行为,因此这种情况被视为错误,导致抛出 \Crossjoin\Json\Exception\InvalidArgumentException
异常。此错误不能使用 json_last_error()
处理,因为错误代码 \JSON_ERROR_UNSUPPORTED_TYPE 在 PHP 5.5.0 之前不存在。