定制 ropi/json-schema-evaluator 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

ropi/json-schema-evaluator

Composer 安装命令:

composer require ropi/json-schema-evaluator

包简介

JSON Schema Evaluator

README 文档

README

This library is a PHP based implementation for evaluating and validating JSON Schemas. The library can be easily extended with your own keywords and drafts.

Requirements

  • PHP >= 8.1
  • ext-bcmath
  • ext-mbstring
  • ext-fileinfo

Table of contents

Installation

The library can be installed from a command line interface by using composer.

Supported drafts

Draft 2020-12 (Core and Validation)

Passes all tests of official JSON schema test suite except the following optional tests:

  • optional/refOfUnknownKeyword.json: This means that you cannot use the $ref keyword to reference schemas that are located inside unknown keywords.
  • optional/ecmascript-regex.json: This means that the specifics of Ecmascript regular expressions are not respected. Instead, regular expressions are evaluated as PERL regular expressions.
composer require ropi/json-schema-evaluator

Basic examples

Basic usage

$schema = json_decode('{
    "type": "string",
    "maxLength": 5
}');

$evaluator = new \Ropi\JsonSchemaEvaluator\JsonSchemaEvaluator();

// Each JSON Schema must be statically analyzed once.
$staticEvaluationContext = $evaluator->evaluateStatic($schema, new \Ropi\JsonSchemaEvaluator\EvaluationConfig\StaticEvaluationConfig(
    defaultDraft: new \Ropi\JsonSchemaEvaluator\Draft\Draft202012()
));

$instance1 = "hello";
$evaluator->evaluate($instance1, $staticEvaluationContext); // Returns true

$instance2 = "helloworld";
$evaluator->evaluate($instance2, $staticEvaluationContext); // Returns false

Read individual error results

$valid = $evaluator->evaluate(
    instance: $instance2,
    staticEvaluationContext: $staticEvaluationContext,
    results: $results
);

foreach ($results as $result) {
    /** @var $result \Ropi\JsonSchemaEvaluator\EvaluationContext\RuntimeEvaluationResult */
    if ($result->type === 'error') {
        echo "Error keyword location: '{$result->keywordLocation}'\n";
        echo "Error instance location: '{$result->instanceLocation}'\n";
        echo "Error message: {$result->error}\n";
    }
}

Output of above example:

Error keyword location: '/maxLength'
Error instance location: ''
Error message: At most 5 characters are allowed, but there are 10.

Formatting results

In the following example, the results are formatted as Basic Output Structure. In addition, only the Flag Output Structure is also currently supported.

$formattedResults = (new \Ropi\JsonSchemaEvaluator\Output\BasicOutput($valid, $results))->format();
echo json_encode($formattedResults, JSON_PRETTY_PRINT);

Output of above example:

{
  "valid": false,
  "errors": [
    {
      "type": "annotation",
      "valid": true,
      "keywordLocation": "\/type",
      "instanceLocation": "",
      "keywordName": "type",
      "error": "",
      "errorMeta": null,
      "annotation": [
        "string"
      ]
    },
    {
      "type": "error",
      "valid": false,
      "keywordLocation": "\/maxLength",
      "instanceLocation": "",
      "keywordName": "maxLength",
      "error": "At most 5 characters are allowed, but there are 10.",
      "errorMeta": null
    }
  ]
}

Mutations

Default values

If a default value is defined with the default keyword, it can be automatically applied during evaluation.

$schema = json_decode('{
    "type": "object",
    "required": ["lastname"],
    "properties": {
        "firstname": {
            "default": "n/a"
        }
    }
}');

$evaluator = new \Ropi\JsonSchemaEvaluator\JsonSchemaEvaluator();

$staticEvaluationContext = $evaluator->evaluateStatic($schema, new \Ropi\JsonSchemaEvaluator\EvaluationConfig\StaticEvaluationConfig(
    defaultDraft: new \Ropi\JsonSchemaEvaluator\Draft\Draft202012(
        evaluateMutations: true
    )
));

$instance = (object) [
    'lastname' => 'Gauss'
];

$evaluator->evaluate($instance, $staticEvaluationContext);

echo $instance->firstname; // Prints "n/a"

Content decoding

If encoded content is defined with the contentEncoding keyword, it can be automatically decoded during evaluation.

$schema = json_decode('{
    "contentMediaType": "application/json",
    "contentEncoding": "base64"
}');

$evaluator = new \Ropi\JsonSchemaEvaluator\JsonSchemaEvaluator();

$staticEvaluationContext = $evaluator->evaluateStatic($schema, new \Ropi\JsonSchemaEvaluator\EvaluationConfig\StaticEvaluationConfig(
    defaultDraft: new \Ropi\JsonSchemaEvaluator\Draft\Draft202012(
        evaluateMutations: true
    )
));

$instance = 'eyJmb28iOiAiYmFyIn0K'; // Base64 encoded JSON '{"foo": "bar"}'

$evaluator->evaluate($instance, $staticEvaluationContext); // Returns true

echo $instance; // Prints '{"foo": "bar"}'

Advanced examples

Assert content media type

If content media type is defined with the contentMediaType keyword, it can be respected during evaluation.

$schema = json_decode('{
    "contentMediaType": "application/json"
}');

$evaluator = new \Ropi\JsonSchemaEvaluator\JsonSchemaEvaluator();

$staticEvaluationContext = $evaluator->evaluateStatic($schema, new \Ropi\JsonSchemaEvaluator\EvaluationConfig\StaticEvaluationConfig(
    defaultDraft: new \Ropi\JsonSchemaEvaluator\Draft\Draft202012(
        assertContentMediaTypeEncoding: true
    )
));

$instance = '{"foo": "bar"}';
$evaluator->evaluate($instance, $staticEvaluationContext); // Returns true

$instance2 = 'invalidJSON';
$evaluator->evaluate($instance2, $staticEvaluationContext); // Returns false

Assert format

If format is defined with the format keyword, it can be respected during evaluation.

$schema = json_decode('{
    "format": "email"
}');

$evaluator = new \Ropi\JsonSchemaEvaluator\JsonSchemaEvaluator();

$staticEvaluationContext = $evaluator->evaluateStatic($schema, new \Ropi\JsonSchemaEvaluator\EvaluationConfig\StaticEvaluationConfig(
    defaultDraft: new \Ropi\JsonSchemaEvaluator\Draft\Draft202012(
        assertFormat: true
    )
));

$instance = 'test@example.com';
$evaluator->evaluate($instance, $staticEvaluationContext, $runtimeEvaluationConfig); // Returns true

$instance2 = 'invalidEmail';
$evaluator->evaluate($instance2, $staticEvaluationContext, $runtimeEvaluationConfig); // Returns false

Short-circuiting

By default, all keywords are evaluated, even if the first keyword validation fails. If short circuiting is activated, the evaluation stops at the first negative validation result.

$config = new \Ropi\JsonSchemaEvaluator\EvaluationConfig\StaticEvaluationConfig(
    defaultDraft: new \Ropi\JsonSchemaEvaluator\Draft\Draft202012(
        shortCircuit: true
    )
);

Big numbers (interpret numeric strings as numbers)

$schema = json_decode('{
    "type": "integer"
}');

$evaluator = new \Ropi\JsonSchemaEvaluator\JsonSchemaEvaluator();

$staticEvaluationContext = $evaluator->evaluateStatic($schema, new \Ropi\JsonSchemaEvaluator\EvaluationConfig\StaticEvaluationConfig(
    defaultDraft: new \Ropi\JsonSchemaEvaluator\Draft\Draft202012(
        acceptNumericStrings: true
    )
));

$instance = json_decode('6565650699413464649797946464646464649797979', false, 512, JSON_BIGINT_AS_STRING);
$evaluator->evaluate($instance, $staticEvaluationContext); // Returns true

Custom keywords

It is possible to add custom keywords to a draft.
The following example shows how to implement a keyword where the instance must match a specific md5 hash.

$schema = json_decode('{
    "md5Hash": "098f6bcd4621d373cade4e832627b4f6"
}');

class Md5HashKeyword extends \Ropi\JsonSchemaEvaluator\Keyword\AbstractKeyword implements \Ropi\JsonSchemaEvaluator\Keyword\RuntimeKeywordInterface
{
    public function getName() : string
    {
        return "md5Hash";
    }

    public function evaluate(mixed $keywordValue, \Ropi\JsonSchemaEvaluator\EvaluationContext\RuntimeEvaluationContext $context): ?\Ropi\JsonSchemaEvaluator\EvaluationContext\RuntimeEvaluationResult
    {
        $instance = $context->getCurrentInstance();
        if (!is_string($instance)) {
            // Ignore keyword, because instance is not a string
            return null;
        }

        $result = $context->createResultForKeyword($this, $keywordValue);

        if (md5($instance) !== $keywordValue) {
            $result->invalidate('MD5 hash of "' . $instance . '" does not match ' . $keywordValue);
        }

        return $result;
    }
}

$draft = new \Ropi\JsonSchemaEvaluator\Draft\Draft202012();
$draft->registerKeyword(new Md5HashKeyword(), 'https://example.tld/draft/2022-03/vocab/md5'); // Register keyword with custom vocabulary

$evaluator = new \Ropi\JsonSchemaEvaluator\JsonSchemaEvaluator();

$staticEvaluationContext = $evaluator->evaluateStatic($schema, new \Ropi\JsonSchemaEvaluator\EvaluationConfig\StaticEvaluationConfig(
    defaultDraft: $draft
));

$instance = 'test';
$evaluator->evaluate($instance, $staticEvaluationContext); // Returns true, because md5 hash matches

$instance = 'hello';
$evaluator->evaluate($instance, $staticEvaluationContext); // Returns false, because md5 hash does not match

统计信息

  • 总下载量: 224
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 5
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2021-08-04

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固