webmozart/ json
一个强大的JSON解码器/编码器,支持模式验证。
Requires
- php: ^5.3.3|^7.0
- justinrainbow/json-schema: ^1.6
- seld/jsonlint: ^1.0
- webmozart/path-util: ^2.3
Requires (Dev)
- phpunit/phpunit: ^4.6
- sebastian/version: ^1.0.1
- symfony/filesystem: ^2.5
This package is auto-updated.
Last update: 2024-09-07 23:56:52 UTC
README
最新版本:1.2.2
一个强大的包装器,用于json_encode()
/json_decode()
,它跨PHP版本标准化其行为,抛出有意义的异常,并默认支持模式验证。
安装
使用Composer安装此包
$ composer require webmozart/json
编码
使用JsonEncoder
将数据编码为JSON
use Webmozart\Json\JsonEncoder; $encoder = new JsonEncoder(); // Store JSON in string $string = $encoder->encode($data); // Store JSON in file $encoder->encodeFile($data, '/path/to/file.json');
默认情况下,使用存储在JSON文档$schema
属性中的JSON模式来验证文件。您还可以在两种方法的最后一个可选参数中传递模式的路径
use Webmozart\Json\ValidationFailedException; try { $string = $encoder->encode($data, '/path/to/schema.json'); } catch (ValidationFailedException $e) { // data did not match schema }
解码
使用JsonDecoder
解码JSON字符串/文件
use Webmozart\Json\JsonDecoder; $decoder = new JsonDecoder(); // Read JSON string $data = $decoder->decode($string); // Read JSON file $data = $decoder->decodeFile('/path/to/file.json');
与JsonEncoder
一样,解码器接受其方法的最后一个可选参数中的JSON模式的路径
use Webmozart\Json\ValidationFailedException; try { $data = $decoder->decodeFile('/path/to/file.json', '/path/to/schema.json'); } catch (ValidationFailedException $e) { // data did not match schema }
验证
有时需要将编码/解码JSON数据和对其模式进行验证的步骤分开。在这种情况下,可以在编码/解码期间省略模式参数,并使用JsonValidator
手动稍后验证数据
use Webmozart\Json\JsonDecoder; use Webmozart\Json\JsonValidator; use Webmozart\Json\ValidationFailedException; $decoder = new JsonDecoder(); $validator = new JsonValidator(); $data = $decoder->decodeFile('/path/to/file.json'); // process $data... $errors = $validator->validate($data, '/path/to/schema.json'); if (count($errors) > 0) { // data did not match schema }
注意:如果使用$schema
属性设置模式(参见下一节),则此方法不起作用。如果设置了该属性,则在编码和解码过程中始终使用该模式进行验证。
模式
鼓励您将JSON文档的模式存储在$schema
属性中
{ "$schema": "http://example.org/schemas/1.0/schema" }
此包中的实用程序将从URL加载模式并将其用于验证文档。显然,这会影响性能,并且取决于服务器的可用性和互联网连接。因此,鼓励您将模式与您的包一起分发。使用LocalUriRetriever
将URL映射到您的本地模式文件
$uriRetriever = new UriRetriever(); $uriRetriever->setUriRetriever(new LocalUriRetriever( // base directory __DIR__.'/../res/schemas', // list of schema mappings array( 'http://example.org/schemas/1.0/schema' => 'schema-1.0.json', ) )); $validator = new JsonValidator(null, $uriRetriever); $encoder = new JsonEncoder($validator); $decoder = new JsonDecoder($validator); // ...
转换
您可以实现JsonConverter
来封装将对象从JSON结构转换为对象并在单个类中封装的转换
use stdClass; use Webmozart\Json\Conversion\JsonConverter; class ConfigFileJsonConverter implements JsonConverter { const SCHEMA = 'http://example.org/schemas/1.0/schema'; public function toJson($configFile, array $options = array()) { $jsonData = new stdClass(); $jsonData->{'$schema'} = self::SCHEMA; if (null !== $configFile->getApplicationName()) { $jsonData->application = $configFile->getApplicationName(); } // ... return $jsonData; } public function fromJson($jsonData, array $options = array()) { $configFile = new ConfigFile(); if (isset($jsonData->application)) { $configFile->setApplicationName($jsonData->application); } // ... return $configFile; } }
现在加载和转储ConfigFile
对象非常简单
$converter = new ConfigFileJsonConverter(); // Load config.json as ConfigFile object $jsonData = $decoder->decodeFile('/path/to/config.json'); $configFile = $converter->fromJson($jsonData); // Save ConfigFile object as config.json $jsonData = $converter->toJson($configFile); $encoder->encodeFile($jsonData, '/path/to/config.json');
您可以通过将转换器包装在ValidatingConverter
中来自动化ConfigFile
的模式验证
use Webmozart\Json\Validation\ValidatingConverter; $converter = new ValidatingConverter(new ConfigFileJsonConverter());
您还可以通过将模式传递给ValidatingConverter
来针对显式模式进行验证
use Webmozart\Json\Validation\ValidatingConverter; $converter = new ValidatingConverter( new ConfigFileJsonConverter(), __DIR__.'/../res/schema/config-schema.json' );
版本控制和迁移
当您持续开发应用程序时,您将进入需要更改您的JSON模式的情况。将JSON文件更新以匹配更改后的模式可能是具有挑战性和耗时的。此包支持版本控制机制来自动化此迁移。
想象一下config.json
文件有三个不同的版本:1.0、2.0和3.0。在这些版本之间,键的名称发生了变化
config.json(版本1.0)
{ "$schema": "http://example.org/schemas/1.0/schema", "application": "Hello world!" }
config.json(版本2.0)
{ "$schema": "http://example.org/schemas/2.0/schema", "application.name": "Hello world!" }
config.json(版本3.0)
{ "$schema": "http://example.org/schemas/3.0/schema", "application": { "name": "Hello world!" } }
您可以通过实现与最新版本(例如3.0)兼容的转换器来支持这些版本中的任何文件
-
兼容最新版本(例如3.0)的转换器
-
将旧版本迁移到新版本(例如从1.0到2.0和从2.0到3.0)的迁移。
让我们看一下3.0版本的ConfigFileJsonConverter
的一个例子。
use stdClass; use Webmozart\Json\Conversion\JsonConverter; class ConfigFileJsonConverter implements JsonConverter { const SCHEMA = 'http://example.org/schemas/3.0/schema'; public function toJson($configFile, array $options = array()) { $jsonData = new stdClass(); $jsonData->{'$schema'} = self::SCHEMA; if (null !== $configFile->getApplicationName()) { $jsonData->application = new stdClass(); $jsonData->application->name = $configFile->getApplicationName(); } // ... return $jsonData; } public function fromJson($jsonData, array $options = array()) { $configFile = new ConfigFile(); if (isset($jsonData->application->name)) { $configFile->setApplicationName($jsonData->application->name); } // ... return $configFile; } }
此转换器可以按照上一节所述使用。然而,它只能与3.0版本的config.json
文件一起使用。
我们可以通过实现JsonMigration
接口来添加对旧文件的支持。该接口包含四个方法
getSourceVersion()
:返回迁移的源版本getTargetVersion()
:返回迁移的目标版本up(stdClass $jsonData)
:从源版本迁移到目标版本down(stdClass $jsonData)
:从目标版本迁移回源版本
use Webmozart\Json\Migration\JsonMigration; class ConfigFileJson20To30Migration implements JsonMigration { const SOURCE_SCHEMA = 'http://example.org/schemas/2.0/schema'; const TARGET_SCHEMA = 'http://example.org/schemas/3.0/schema'; public function getSourceVersion() { return '2.0'; } public function getTargetVersion() { return '3.0'; } public function up(stdClass $jsonData) { $jsonData->{'$schema'} = self::TARGET_SCHEMA; if (isset($jsonData->{'application.name'})) { $jsonData->application = new stdClass(); $jsonData->application->name = $jsonData->{'application.name'}; unset($jsonData->{'application.name'}); ) } public function down(stdClass $jsonData) { $jsonData->{'$schema'} = self::SOURCE_SCHEMA; if (isset($jsonData->application->name)) { $jsonData->{'application.name'} = $jsonData->application->name; unset($jsonData->application); ) } }
有了这样的迁移列表,我们可以创建一个装饰我们的ConfigFileJsonConverter
的MigratingConverter
use Webmozart\Json\Migration\MigratingConverter; use Webmozart\Json\Migration\MigrationManager; // Written for version 3.0 $converter = new ConfigFileJsonConverter(); // Support for older versions. The order of migrations does not matter. $migrationManager = new MigrationManager(array( new ConfigFileJson10To20Migration(), new ConfigFileJson20To30Migration(), )); // Decorate the converter $converter = new MigratingConverter($converter, $migrationManager);
生成的转换器能够加载和转储任何版本的1.0、2.0和3.0的JSON文件。
// Loads a file in version 1.0, 2.0 or 3.0 $jsonData = $decoder->decodeFile('/path/to/config.json'); $configFile = $converter->fromJson($jsonData); // Writes the file in the latest version by default (3.0) $jsonData = $converter->toJson($configFile); $encoder->encodeFile($jsonData, '/path/to/config.json'); // Writes the file in a specific version $jsonData = $converter->toJson($configFile, array( 'targetVersion' => '2.0', )); $encoder->encodeFile($jsonData, '/path/to/config.json');
不同版本的验证
如果您想添加模式验证,请将您的编码器包装到ValidatingConverter
中。您可以将内部和外部转换器都包装起来,以确保运行迁移前后的JSON都符合相应的模式。
// Written for version 3.0 $converter = new ConfigFileJsonConverter(); // Decorate to validate against the schema at version 3.0 $converter = new ValidatingConverter($converter); // Decorate to support different versions $converter = new MigratingConverter($converter, $migrationManager); // Decorate to validate against the old schema $converter = new ValidatingConverter($converter);
如果您将版本存储在version
字段中(见下文),并且想根据该版本使用自定义模式,则可以传递用于解析模式路径的schema路径或闭包
// Written for version 3.0 $converter = new ConfigFileJsonConverter(); // Decorate to validate against the schema at version 3.0 $converter = new ValidatingConverter($converter, __DIR__.'/../res/schema/config-schema-3.0.json'); // Decorate to support different versions $converter = new MigratingConverter($converter, $migrationManager); // Decorate to validate against the old schema $converter = new ValidatingConverter($converter, function ($jsonData) { return __DIR__.'/../res/schema/config-schema-'.$jsonData->version.'.json' });
使用自定义模式版本化
默认情况下,模式的版本存储在模式名称中
{ "$schema": "http://example.com/schemas/1.0/my-schema" }
版本必须用斜杠括起来。将版本附加到模式上,例如,是不行的
{ "$schema": "http://example.com/schemas/my-schema-1.0" }
但是,您可以通过创建一个具有自定义正则表达式的SchemaUriVersioner
来自定义模式URI的格式
use Webmozart\Json\Versioning\SchemaUriVersioner; $versioner = new SchemaUriVersioner('~(?<=-)\d+\.\d+(?=$)~'); $migrationManager = new MigrationManager(array( // migrations... ), $versioner); // ...
正则表达式必须仅匹配版本。请确保将版本前后字符包裹在前瞻和后顾断言中((?<=...)
,(?=...)
)。
在字段中存储版本
除了在模式URI中存储版本,您还可以在单独的字段中存储它。例如,字段"version"
{ "version": "1.0" }
此用例由VersionFieldVersioner
类支持
use Webmozart\Json\Versioning\VersionFieldVersioner; $versioner = new VersionFieldVersioner(); $migrationManager = new MigrationManager(array( // migrations... ), $versioner); // ...
VersionFieldVersioner
的构造函数可选地接受一个用于存储版本的自定义字段名称。默认字段名称是"version"。
作者
贡献
对这个包的贡献总是受欢迎的!
支持
如果您遇到问题,请给[email protected]发邮件或在Twitter上呼喊@webmozart。
许可
本包的所有内容均根据MIT许可证授权。