helmich/schema2class

从JSON schema定义构建PHP类

v3.3.4 2024-09-04 14:53 UTC

README

自动从JSON schemas构建PHP类。

示例

考虑一个简单的JSON schema(讽刺的是以YAML格式存储),存储在文件example.yaml

required:
  - givenName
  - familyName
properties:
  givenName:
    type: string
  familyName:
    type: string
  hobbies:
    type: array
    items:
      type: string
  location:
    properties:
      country:
        type: string
      city:
        type: string 

使用此转换器,您可以自动从这个schema生成带有访问器和转换函数的PHP类

$ vendor/bin/s2c generate:fromschema --class User ./example.yaml src/Target

此命令将自动尝试从您的composer.json文件中推断PHP目标命名空间,并自动创建相应的PHP类

$ find src/Target
src/Target
src/Target/User.php
src/Target/UserLocation.php

然后,在您的代码中使用这些类

$userData = json_decode("user.json", true);
$user = \MyNamespace\Target\User::buildFromInput($userData);

echo "Hello, " . $user->getGivenName() . "\n";

兼容性

此工具需要PHP 8.2或更高版本才能运行。

生成的代码可以向后兼容到PHP 5.6。使用--target-php标志设置生成的代码应兼容的PHP版本。当使用配置文件时,使用targetPHPVersion属性。

创建结果

生成的类具有以下功能

  • 类命名空间可以通过命令行(--target-namespace)、规范文件(targetNamespace)指定。如果没有指定,生成器将检查您的项目的composer.json,查找任何PSR-4配置,并从中推断命名空间。
  • 主对象的名称由命令行(--class)或规范文件定义。
  • 子对象的名称取自属性名称。
  • 数组项后缀为'Item'。
  • OneOf选项后缀为'AlternativeX',其中X是递增的整数。
  • 构造函数具有对schema中所有必需属性的参数。
  • 所有属性都是私有的,有getter方法进行访问,并具有显式的返回值类型声明(在PHP5模式下,仅使用PHPDoc)。
  • 静态函数buildFromInput(array $data)接受一个数组(使用json_decode('{}', true)),根据schema进行验证,并创建完整的对象树作为返回值。不需要额外的映射步骤。
  • 函数toJson()返回一个用于json_encode()的纯数组。
  • 通过使用withX()(或用于可选值的withoutX())不可变地写入任何对象的属性。这将返回一个包含值更改的新实例。

以下是一个从上述schema中删除所有注释的简短版本示例,仅包含城市位置(国家行为相同,但名称不同)

class UserLocation
{
    private static array $schema = array(
        'properties' => array(
            'city' => array(
                'type' => 'string',
            ),
        ),
    );

    private ?string $country = null;

    private ?string $city = null;

    public function __construct()
    {
    }

    public function getCity() : ?string
    {
        return $this->city;
    }

    public function withCity(string $city) : self
    {
        $validator = new \JsonSchema\Validator();
        $validator->validate($city, static::$schema['properties']['city']);
        if (!$validator->isValid()) {
            throw new \InvalidArgumentException($validator->getErrors()[0]['message']);
        }

        $clone = clone $this;
        $clone->city = $city;

        return $clone;
    }

    public function withoutCity() : self
    {
        $clone = clone $this;
        unset($clone->city);

        return $clone;
    }

    public static function buildFromInput(array $input) : UserLocation
    {
        static::validateInput($input);

        $city = null;
        if (isset($input['city'])) {
            $city = $input['city'];
        }

        $obj = new static();
        $obj->city = $city;
        return $obj;
    }

    public function toJson() : array
    {
        $output = [];
        if (isset($this->city)) {
            $output['city'] = $this->city;
        }

        return $output;
    }

    public static function validateInput(array $input, bool $return = false) : bool
    {
        $validator = new \JsonSchema\Validator();
        $validator->validate($input, static::$schema);

        if (!$validator->isValid() && !$return) {
            $errors = array_map(function($e) {
                return $e["property"] . ": " . $e["message"];
            }, $validator->getErrors());
            throw new \InvalidArgumentException(join(", ", $errors));
        }

        return $validator->isValid();
    }

    public function __clone()
    {
    }
}

安装

使用Composer进行安装

$ composer require --dev helmich/schema2class

使用配置文件

在许多项目中,您可能希望将不断发展的JSON schema与生成的PHP类持续同步。为此,S2C允许您创建一个配置文件.s2c.yaml,该文件存储最常用的转换选项

targetPHPVersion: "7.4"
files:
- input: src/Spec/Spec.yaml
  className: Specification
  targetDirectory: src/Spec

您可以将本地配置存储在此yaml文件中,并通过调用启动生成过程

s2c generate:fromspec

这将扫描当前目录中的.s2c.yaml并使用其参数。如果您需要为多个schema提供不同的文件,您可以提供配置文件作为参数。