如何用Karate DSL验证含动态嵌套对象的JSON Schema
Karate DSL 验证含可选嵌套对象的 JSON Schema
问题原因分析
你遇到的问题核心是:
- 初始写法中
"paymentSummary":"##(outerSchema)"强制要求所有记录必须包含该字段,因此第二条缺失paymentSummary的记录验证失败。 - 错误修改为
"paymentSummary":"##object outerSchema"属于语法误用,Karate 中引用预定义 Schema 需用##(schemaName)格式,这种混合写法会导致类型转换异常。
解决方案:标记字段为可选
Karate 提供两种方式标记字段为可选,允许部分记录缺失该字段,同时对存在的字段验证其结构:
方式一:使用##optional关键字
在字段的规则前添加##optional,表示字段可以不存在,若存在则必须符合指定 Schema:
* def response = """ { "records": [ { "recordId": 1, "firstName": "John", "lastName": "Doe", "paymentSummary": { "paymentId": 123, "totalPaymentAmount": 1000, "recentPayment": { "paymentDate": "01/01/2025", "recentPaymentAmt": 200 } } }, { "recordId": 2, "firstName": "John", "lastName": "Ted" } ] } """ # 定义 recentPayment 的 Schema(修正正则转义问题) * def innerSchema = """ { "paymentDate": "##regex ^(0[1-9]|1[0-2])/(0[1-9]|[12]\\d|3[01])/\\d{4}$", "recentPaymentAmt": "##number" } """ # 定义 paymentSummary 的 Schema * def outerSchema = """ { "paymentId": "##number", "totalPaymentAmount": "##number", "recentPayment": "##(innerSchema)" } """ # 定义整体记录 Schema,标记 paymentSummary 为可选 * def responseSchema = """ { "recordId": "##number", "firstName": "##string", "lastName": "##string", "paymentSummary": "##optional ##(outerSchema)" } """ * match each response.records == responseSchema
方式二:在字段名前加?前缀
直接在可选字段的 key 前添加?,同样表示该字段为可选:
# 替换上述 responseSchema 为以下内容即可 * def responseSchema = """ { "recordId": "##number", "firstName": "##string", "lastName": "##string", "?paymentSummary": "##(outerSchema)" } """
额外修正说明
- 原代码中
"firstName":"string"需修正为"firstName":"##string",符合 Karate 官方 Schema 验证的规范写法。 - 正则表达式中的
\d在 JSON 字符串中需转义为\\d,避免解析异常。
验证效果
修改后两条记录均可通过验证:
- 第一条存在
paymentSummary的记录,会验证其嵌套结构是否符合outerSchema定义。 - 第二条缺失
paymentSummary的记录,会跳过该字段的验证逻辑,仅检查必填字段的合法性。
内容的提问来源于stack exchange,提问作者Gohila Mani
相关产品推荐
相关产品推荐

