You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JSON Schema验证中实现指定字段的类型转换?

JSON Schema类型转换问题(基于opis/json-schema库)

标准JSON Schema的限制

标准JSON Schema(包括draft-07版本)仅负责验证数据的结构、格式和约束,原生不提供类型转换功能。你提到的default关键字是唯一能修改输入数据的特性,但它仅用于补全缺失的属性值,不涉及类型转换。

基于opis/json-schema库的解决方案

针对PHP环境下的opis/json-schema库,我们可以通过两种方式实现你的类型转换需求:

1. 验证后手动处理类型转换

这是最直接的方案:先通过Schema完成数据验证,再对需要转换的属性单独处理(因为Schema已确保格式合法,转换大概率不会失败)。

示例代码:

use Opis\JsonSchema\Validator;

// 你的基础验证Schema
$schema = [
    "$schema" => "https://json-schema.org/draft-07/schema",
    "type" => "object",
    "properties" => [
        "some_key" => [
            "anyOf" => [
                ["type" => "integer"],
                ["type" => "string", "pattern" => "^(0|[1-9][0-9]*)$"]
            ]
        ],
        // 其他需要转换的属性示例
        "another_key" => [
            "anyOf" => [
                ["type" => "string"],
                ["type" => "integer"]
            ]
        ]
    ],
    "required" => ["some_key"],
    "additionalProperties" => false
];

// 待处理的输入数据
$input = ["some_key" => "123", "another_key" => 456];

// 第一步:验证数据合法性
$validator = new Validator();
$result = $validator->validate($input, $schema);

if ($result->isValid()) {
    // 定义需要转换的属性规则:键为属性名,值为目标类型
    $convertRules = [
        "some_key" => "integer", // 符合格式的字符串转整数
        "another_key" => "string" // 数字转字符串
    ];

    // 遍历执行转换
    foreach ($convertRules as $key => $targetType) {
        if (!isset($input[$key])) continue;

        $value = $input[$key];
        switch ($targetType) {
            case "integer":
                if (is_string($value)) {
                    $input[$key] = (int)$value;
                }
                break;
            case "string":
                if (is_int($value)) {
                    $input[$key] = (string)$value;
                }
                break;
        }
    }

    // $input现在是转换完成的合法数据
    var_dump($input);
} else {
    // 处理验证错误
    var_dump($result->error());
}

2. 自定义JSON Schema关键字实现自动转换

opis/json-schema支持自定义关键字,你可以创建一个如convertTo的关键字,让验证过程中自动完成类型转换,适合多属性、需要复用转换规则的场景。

示例代码(自定义关键字):

use Opis\JsonSchema\Validator;
use Opis\JsonSchema\Schema;
use Opis\JsonSchema\ValidationContext;
use Opis\JsonSchema\Keyword;

// 自定义转换关键字的处理器
class ConvertToKeyword implements Keyword
{
    public function validate(mixed $data, Schema $schema, ValidationContext $context): void
    {
        $targetType = $schema->data()->get('convertTo');
        if (!$targetType) return;

        $converted = null;
        switch ($targetType) {
            case 'integer':
                if (is_string($data) && preg_match('/^(0|[1-9][0-9]*)$/', $data)) {
                    $converted = (int)$data;
                } elseif (is_int($data)) {
                    $converted = $data; // 本身是整数,无需转换
                }
                break;
            case 'string':
                if (is_int($data)) {
                    $converted = (string)$data;
                } elseif (is_string($data)) {
                    $converted = $data; // 本身是字符串,无需转换
                }
                break;
        }

        if ($converted !== null) {
            // 修改上下文数据,完成转换
            $context->setData($converted);
        } else {
            // 转换失败,抛出验证错误
            $context->error('数据类型不符合转换要求', 'convertTo');
        }
    }
}

// 注册自定义关键字到验证器
$validator = new Validator();
$validator->registerKeyword('convertTo', new ConvertToKeyword());

// 更新Schema,为需要转换的属性添加convertTo关键字
$schema = [
    "$schema" => "https://json-schema.org/draft-07/schema",
    "type" => "object",
    "properties" => [
        "some_key" => [
            "convertTo" => "integer",
            "anyOf" => [
                ["type" => "integer"],
                ["type" => "string", "pattern" => "^(0|[1-9][0-9]*)$"]
            ]
        ],
        "another_key" => [
            "convertTo" => "string",
            "anyOf" => [
                ["type" => "string"],
                ["type" => "integer"]
            ]
        ]
    ],
    "required" => ["some_key"],
    "additionalProperties" => false
];

$input = ["some_key" => "123", "another_key" => 456];
$result = $validator->validate($input, $schema);

if ($result->isValid()) {
    // 获取转换后的完整数据
    $processedData = $result->data();
    var_dump($processedData);
} else {
    var_dump($result->error());
}

总结

  • 标准JSON Schema不支持类型转换,必须依赖具体库的扩展或手动处理。
  • 手动处理适合简单场景,自定义关键字更适合多属性、需要复用转换规则的场景。
  • 两种方式都能实现你需要的“字符串转数字”或“数字转字符串”需求,且转换失败时可通过验证逻辑抛出错误。

内容的提问来源于stack exchange,提问作者afiori

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 21:40:59