跳转到内容

JSON Schema 支持

🧪 实验性功能

JSON Schema 支持本质上是将其转换为 Valibot Schema,然后由 Piying-View 正常解析。

Piying-View 提供 jsonSchemaToValibot 函数,将 JSON Schema(支持 Draft-04、Draft-07、Draft 2020-12)转换为 Valibot Schema:

import { jsonSchemaToValibot } from '@piying/view-angular-core/adapter';

const valibotSchema = jsonSchemaToValibot(jsonSchema);
// 转换后即可与传统的 Piying-View 使用方式一致
JSON Schema 类型 Valibot 对应
string v.string()
number v.number()
integer v.integer()
boolean v.boolean()
null v.null()
any / 无 type v.any()
JSON Schema Valibot 转换
type: "string", minLength v.pipe(v.string(), v.minLength(N))
type: "number", minimum v.pipe(v.number(), v.minValue(N))
type: "integer", minimum v.pipe(v.integer(), v.minValue(N))
enum: ["a", "b"] v.picklist(["a", "b"])
const: 1 v.literal(1)
JSON Schema 结构 Valibot 对应
properties + required v.object()(必填字段自动标记)
properties(无 required) v.looseObject()
prefixItems v.tuple() / v.looseTuple() / v.tupleWithRest()
无 properties + additionalProperties v.record()
JSON Schema 结构 Valibot 对应
items(非数组) v.array(itemsSchema)
items(数组,含 uniqueItems) v.array(itemsSchema) + 去重约束
JSON Schema Valibot 对应
oneOf v.union()oneOf-condition 组件)
anyOf v.intersect() + v.union()anyOf-condition 组件)
allOf v.intersect()
if/then/else v.pipe() + 条件逻辑

传入的数据不可存在死结(某些字段在验证过程中始终失败则为死结):

{
  "propertyNames": false,
  "properties": { "a": { "type": "string" } },
  "required": ["a"]
}

const / enum 出现时优先转换,忽略其他验证:

{
  // ✅ enum 优先
  "enum": [1, 2, 3],
  // 🚫 type 被忽略
  "type": "string"
}

一个 schema 中只允许出现 allOf / oneOf / anyOf / if/then/else 其中之一not 不在此限制中):

// ❌ 不允许同时使用多个组合关键字
{ "allOf": [], "oneOf": [] }

// ✅ 只使用一个
{ "allOf": [] }

allOf / oneOf / anyOf / if/then/else 子模式内不支持嵌套子模式:

{
  "allOf": [
    {
      // ❌ anyOf 不允许嵌套在 allOf 内
      "anyOf": []
    }
  ]
}

$ref 仅支持单文件,不支持远程引用。

Piying-View 根据 JSON Schema 结构自动选择合适的组件渲染策略:

适用场景:子模式下存在相同字段时。

{
  "oneOf": [
    {
      "properties": {
        "cond1": { "const": 1 },
        "value1": { "type": "string" }
      },
      "required": ["cond1"]
    },
    {
      "properties": {
        "cond1": { "const": 2 },
        "value2": { "type": "string" }
      },
      "required": ["cond1"]
    }
  ]
}

适用场景:需要组件中实现手动选择一个或多个子条件。

{
  "oneOf": [
    {
      "title": "item1",
      "properties": {
        "value1": { "type": "string" }
      }
    },
    {
      "title": "item2",
      "properties": {
        "value2": { "type": "string" }
      }
    }
  ]
}
JSON Schema 映射
properties + required v.object()(严格模式)
properties(无 required) v.looseObject()(宽松模式,保留未定义键值)
带 rest 的 object objectWithRest / intersect
JSON Schema 映射
prefixItems + 无 additionalItems v.tuple()(固定长度,超出自动过滤)
prefixItems + additionalItems: true v.looseTuple()(保留超出部分)
部分固定 + rest v.tupleWithRest()

可视为普通的 object 类型,主要用于验证场景。

以下类型会自动传入 options 输入属性到对应组件,组件需要实现选项渲染:

JSON Schema Valibot 组件类型 说明
"enum": ["1", "2"] v.picklist() 由类型映射决定 单选
"items": { "enum": [...] }, "uniqueItems": true v.array() multiselect 多选,不可重复选择
"items": { "enum": [...] }(无 uniqueItems v.array() multiselect-repeat 多选,可以重复选择
"type": "number", "minimum": N v.number() 由类型映射决定 数值输入

⚠️ 多选分支的组件名由 uniqueItems 直接决定:uniqueItems ? 'multiselect' : 'multiselect-repeat'。即uniqueItems 才是不可重复的 multiselect,不带时反而是可重复的 multiselect-repeat。多选分支还会额外附加 asControl()multiple: true 输入。

在 JSON Schema 中定义 actions 字段即可使用内置的 Piying-View Actions:

{
  "type": "string",
  "title": "Select 4: Radio button",
  "enum": ["Option 1", "Option 2", "Option 3"],
  "actions": [
    {
      "name": "setComponent",
      "params": ["radio"]
    }
  ]
}

如果 JSON Schema 中包含其他自定义的 actions,则需要通过 jsonSchemaToValibot 的第二个参数 customActions 注册:

{
  "type": "string",
  "actions": [
    {
      "name": "testTitle",
      "params": []
    }
  ]
}
import * as v from 'valibot';
import { jsonSchemaToValibot } from '@piying/view-angular-core/adapter';

const schema = jsonSchemaToValibot(jsonSchema, {
  customActions: {
    // 名称对应 JSON 中 actions[].name,params 逐个展开为函数参数
    testTitle: () => v.title('测试标题'),
  },
});
import * as v from 'valibot';
import { jsonSchemaToValibot } from '@piying/view-angular-core/adapter';
import { PiyingView, BaseControl, PiyingViewGroup } from '@piying/view-angular';

// JSON Schema 定义
const jsonSchema = {
  type: 'object',
  properties: {
    username: { type: 'string', minLength: 3, title: '用户名' },
    age: { type: 'integer', minimum: 0, maximum: 150, title: '年龄' },
    role: { type: 'string', enum: ['admin', 'user'], title: '角色' },
    address: {
      type: 'object',
      properties: {
        city: { type: 'string' },
        street: { type: 'string' },
      },
      required: ['city'],
    },
  },
  required: ['username', 'age'],
};

// 转换为 Valibot Schema
const schema = jsonSchemaToValibot(jsonSchema);

// 后续使用方式与传统 Piying-View 完全一致