首页 > Java > java教程 > 正文

JSON Schema高级教程:基于嵌套属性的条件必填校验

心靈之曲
发布: 2025-11-27 20:40:41
原创
650人浏览过

json schema高级教程:基于嵌套属性的条件必填校验

JSON Schema作为一种强大的数据结构描述语言,广泛应用于API请求体、配置文件等场景的数据验证。然而,在面对复杂的业务逻辑时,例如根据某个字段的值来动态地改变其他字段的必填性,尤其是当这些字段处于不同层级时,往往会遇到挑战。本文将详细阐述如何利用JSON Schema的条件关键字,实现基于嵌套属性的顶层属性条件必填校验。

问题场景:基于订单类型的商品列表必填

设想一个订单验证场景,我们有一个Order对象,其中包含attributes嵌套对象,而attributes中又有一个order_type字段。我们的需求是:

  • 当attributes.order_type的值为"ORDER"时,顶层的items属性必须存在且非空。
  • 对于order_type的其他值(如"TRANSFER"、"WITHDRAWAL"等),items属性是可选的。

最初的尝试可能倾向于将条件逻辑放置在attributes属性的定义内部,例如在attributes的allOf数组中添加对items的required校验。然而,这种做法是无效的。JSON Schema中required关键字的作用域是其所在的当前JSON对象。这意味着,如果if/then块位于attributes的定义内部,其then块中的required只能作用于attributes自身的子属性,而无法影响到与attributes同级的items属性。

JSON Schema条件逻辑:if、then与allOf

为了解决这类问题,我们需要借助JSON Schema提供的条件关键字:

  • if: 定义一个子模式作为条件。如果数据实例符合if子模式,则应用then子模式。
  • then: 当if条件满足时,需要应用的数据模式。
  • allOf: 用于组合多个子模式。数据实例必须同时满足allOf数组中的所有子模式才能通过验证。

关键在于,if/then块的放置位置决定了其作用域。要使条件逻辑能够影响到与attributes同级的items属性,if/then块必须放置在顶层(根级别),与properties和required关键字处于同一层级。

Remusic
Remusic

Remusic - 免费的AI音乐、歌曲生成工具

Remusic 514
查看详情 Remusic

解决方案:在根级别应用条件逻辑

正确的做法是,在主Schema的根级别添加一个allOf块,并在其中定义我们的条件逻辑。这个if条件需要能够“看到”并判断嵌套的attributes.order_type字段。

以下是实现上述需求的完整JSON Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://json-schema.org/draft-07/schema#",
  "title": "Validaciones sobre el esquema Order",
  "type": "object",
  "properties": {
    "warehouse_id": {
      "type": [
        "string"
      ]
    },
    "operation_type": {
      "type": [
        "string"
      ]
    },
    "order_id": {
      "type": [
        "number"
      ]
    },
    "items": {
      "type": [
        "array"
      ],
      "minItems": 1,
      "items": {
        "type": [
          "object"
        ],
        "properties": {
          "sku": {
            "type": [
              "string"
            ],
            "minLength": 1,
            "maxLength": 50
          },
          "quantity": {
            "type": [
              "integer"
            ],
            "minimum": 1
          }
        },
        "required": [
          "sku",
          "quantity"
        ],
        "additionalProperties": false
      }
    },
    "attributes": {
      "type": [
        "object"
      ],
      "properties": {
        "order_type": {
          "type": [
            "string"
          ],
          "enum": [
            "ORDER",
            "TRANSFER",
            "WITHDRAWAL",
            "DISPOSAL",
            "FRESH"
          ]
        },
        "etd": {
          "type": [
            "string"
          ],
          "pattern": "^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])(?:T)(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|1[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])(?:Z)$"
        },
        "volume": {
          "type": [
            "integer", "null"
          ],
          "minimum": 0
        },
        "typology": true
      },
      "required": [
        "order_type"
      ],
      "allOf": [
        {
          "if": {
            "properties": {
              "order_type": {
                "const": "ORDER"
              }
            },
            "required": [
              "order_type"
            ]
          },
          "then": {
            "properties": {
              "order_type": true,
              "etd": true,
              "volume": true,
              "typology": {
                "type": [
                  "string", "null"
                ],
                "enum": [
                  "CONVEYABLE",
                  "NON_CONVEYABLE"
                ]
              }
            },
            "required": [
              "order_type",
              "etd"
            ],
            "additionalProperties": false
          }
        },
        {
          "if": {
            "properties": {
              "order_type": {
                "const": "TRANSFER"
              }
            },
            "required": [
              "order_type"
            ]
          },
          "then": {
            "properties": {
              "order_type": true,
              "etd": true,
              "volume": true
            },
            "required": [
              "order_type",
              "etd"
            ],
            "additionalProperties": false
          }
        },
        {
          "if": {
            "properties": {
              "order_type": {
                "const": "WITHDRAWAL"
              }
            },
            "required": [
              "order_type"
            ]
          },
          "then": {
            "properties": {
              "order_type": true,
              "etd": true,
              "volume": true
            },
            "required": [
              "order_type",
              "etd"
            ],
            "additionalProperties": false
          }
        },
        {
          "if": {
            "properties": {
              "order_type": {
                "const": "DISPOSAL"
              }
            },
            "required": [
              "order_type"
            ]
          },
          "then": {
            "properties": {
              "order_type": true,
              "etd": true,
              "volume": true
            },
            "required": [
              "order_type",
              "etd"
            ],
            "additionalProperties": false
          }
        }
      ]
    }
  },
  "required": [
    "warehouse_id",
    "operation_type",
    "attributes"
  ],
  "additionalProperties": false,
  "allOf": [
    {
      "if": {
        "properties": {
          "attributes": {
            "properties": {
              "order_type": { "const": "ORDER" }
            },
            "required": ["order_type"]
          }
        },
        "required": ["attributes"]
      },
      "then": {
        "required": ["items"]
      }
    }
  ]
}
登录后复制

核心Schema解析

让我们聚焦于解决问题的关键部分——位于根级别的allOf块:

  "allOf": [
    {
      "if": {
        "properties": { // 匹配当前(根)对象的属性
          "attributes": { // 检查名为 "attributes" 的属性
            "properties": {
              "order_type": { "const": "ORDER" } // 进一步检查 "attributes" 内部的 "order_type" 属性,其值必须是 "ORDER"
            },
            "required": ["order_type"] // 确保 "attributes" 对象中包含 "order_type"
          }
        },
        "required": ["attributes"] // 确保根对象中包含 "attributes" 属性
      },
登录后复制

以上就是JSON Schema高级教程:基于嵌套属性的条件必填校验的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号