0

0

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

心靈之曲

心靈之曲

发布时间:2025-11-27 20:40:41

|

683人浏览过

|

来源于php中文网

原创

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关键字处于同一层级。

Copy Leaks
Copy Leaks

AI内容检测和分级,帮助创建和保护原创内容

下载

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

正确的做法是,在主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数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

411

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

533

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

309

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

74

2025.09.10

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

738

2023.08.22

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

534

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

14

2026.01.06

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.3万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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