foamzou/easy-json-schema

该软件包最新版本(1.0)没有提供许可证信息。

1.0 2019-07-23 11:42 UTC

This package is auto-updated.

Last update: 2024-09-20 17:58:05 UTC


README

英文 | 简体中文

Easy Json Schema

当然,我推荐您使用 protobuf。

  • 使用 PHP 对象轻松定义 Json-Schema(支持 draft-07 和 draft-06)
  • 使用 opis/json-schema 作为验证器

优点

  • 易于定义,避免复杂的 json-schema
  • 更易读
  • 更容易维护

安装

composer require "foamzou/easy-json-schema"

用法

use Foamzou\EasyJsonSchema\Manager\Validator;
use Foamzou\EasyJsonSchema\Manager\Parser;
use Foamzou\EasyJsonSchema\Type\{
    Str, Integer
};

// define a schema
$schema = new Obj([
              'name' => (new Integer)->min(2)->max(5),
              'age' => (new Str)->max(120),
          ]);

$data = [
    'name' => 'foam',
    'age' => 18,
];

// generate json-schema
$jsonSchema = Parser::run($schema);

// check is valid with data,errorMessage will return while valid failed
$bool = Validator::getInstance()->isValid($jsonSchema, $data, $errorMessage);

定义模式

以下是与 json-schema 的比较。您可以看到使用 PHP 对象的定义更简单、更易读且更易于维护。

Easy-Json-Schema

new Obj([
    'name'  => (new Integer)->min(2)->max(5),
    'age'   => (new Str)->min(16)->max(120),
    'skill' => (new Arr)->items((new Obj([
        'name'  => (new Str())->min(1)->max(64),
        'value' => (new Num())->min(0)->max(100)->multipleOf(0.25),
    ]))->requiredAll()->additionalProp(false)),
]);

Json-Schema

{
    "type": "object",
    "properties": {
        "name": {
            "type": "integer",
            "minimum": 2,
            "maximum": 5
        },
        "age": {
            "type": "string",
            "minLength": 16,
            "maxLength": 120
        },
        "skill": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64
                    },
                    "value": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100,
                        "multipleOf": 0.25
                    }
                },
                "required": [
                    "name",
                    "value"
                ],
                "additionalProperties": false
            }
        }
    }
}

数据类型

use Foamzou\EasyJsonSchema\Type\{
    Str, Integer, Num, Obj, Boolean, Arr, Nul
};

String

(new Str)->min(1)->max(23)->pattern('/regex/')->contentEncoding()->contentMediaType()

Number

(new Num)->min(1)->max(20); // >=1 and <=20
(new Num)->exMin(1)->exMax(20)->multipleOf(5);// >1 and <20 and divisible by 5

Integer

(new Integer)->min(1)->max(20); // >=1 and <=20
(new Integer)->exMin(1)->exMax(20)->multipleOf(5);// >1 and <20 and divisible by 5

Boolean

new Boolean

Null

new Nul

Array

(new Arr)->items(new obj([
    'name'  => new Integer,
    'age'   => new Str,
]))->min('Array length minimum')
    ->max('Array length minimum')
    ->uniq('bool: Whether the element is required to be unique')
    ->additionalItems('extra element')
    ->contains('contains elements');

Object

(new Obj([
    'name' => new Str,
    'age' => new Integer,
    'childObj' => new Obj([ // can be nested
        'newName' => new Str,
        'newAge' => new Integer,
    ])
]))->required(['name', 'age']);

keyword

Enum

new Enum([1, 2, 3]);

Constant

new Constant('mustBeMe');

AnyOf, OneOf, AllOf

// new objects
new OneOf([
    new Integer,
    new Str,
]);

// call method
(new Arr())->items(new Integer)->oneOf([
    [
        "items"=> [
            "exclusiveMinimum"=> 0
        ]
    ],
    [
        "items"=> [
            "exclusiveMaximum"=> 0
        ]
    ],
    [
        "items"=> [
            "const"=> 0
        ]
    ]
]);


not

new Not(new Str)

if.then.else

// new objects
(new Kif(new Integer()))
    ->then(["minLength" => 3])
    ->else(["const" => 0]);

// call method
(new Obj)->if([
    'properties' => [
        'gender' => new Constant('female')
    ]
])->then([
    'properties' => [
        'gender'    => new Constant('female'),
        'age'       => (new Integer)->min(16),
    ]
])->else([
    'properties' => [
        'gender'    => new Constant('male'),
        'age'       => (new Integer)->min(18),
    ]
]);

重用模式

当模式需要重用其他模式时,可以使用 require

new Obj([
       'name' => (new Str()),
       'location' => require __DIR__ . '/Location.php',
 ]);

常用方法

所有对象都有一个 desc 方法来描述对象

(new Obj([
    'name' => (new Str)->desc('username'),
    'age' => (new Integer)->desc('user age'),
]))->desc('I am a request object');

基于 Type 的对象有 default 方法来设置默认值

(new Str)->default('jay');

编译 EasyJsonSchema 到 Json Schema

use Foamzou\EasyJsonSchema\Manager\Parser;

$schema = (new Obj([
              'name' => (new Str)->desc('username'),
              'age' => (new Integer)->desc('user age'),
          ]))->desc('I am a request object');

$jsonSchema = Parser::run($schema);

检查数据和获取错误信息

如果数据与模式不匹配,则 isValid 将返回 false,否则将返回 true

use Foamzou\EasyJsonSchema\Manager\Validator;

$validator = Validator::getInstance();
$isValid = $validator->isValid($jsonSchema, json_encode($data), $errMessage, $errList);

$errMessage 和 $errList 在 isValid 返回 false 时有值

$errMessage 是一个语义字符串,$errList 是包含 Opis\JsonSchema\ValidationError 的项的数组

当 $errMessage 不是您希望的内容时,您可以使用 $errList 构建您想要的错误消息