【问题标题】:JSON-Schema, basic sample doesn't validateJSON-Schema,基本示例未验证
【发布时间】:2017-11-15 18:35:24
【问题描述】:

我有以下示例架构:

{
    "id": "http://schema.acme.com/widgets",
    "$schema": "http://json-schema.org/draft-06/schema#",
    "definitions": {
        "bentWidget": {
            "type": "object",
            "required": ["angle", "baseWidget"],                        
            "properties": {
                "angle": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 90
                },
                "baseWidget": {
                    "$ref": "#/definitions/baseWidget"
                }
            }
        },
        "highPowerWidget": {
            "type": "object",
            "required": ["power", "baseWidget"],            
            "properties": {
                "power": {
                    "type": "number",
                    "minimum": 101,
                    "maximum": 200
                },
                "baseWidget": {
                    "$ref": "#/definitions/baseWidget"
                }
            }
        },
        "color": {
            "description": "the color of a widget",
            "type": "string"
        },
        "baseWidget": {
            "description": "The base type for a widget",
            "type": "object",
            "required": [
                "title",
                "version",
                "colors"
            ],
            "properties": {
                "title": {
                    "type": "string",
                    "maximum": 100,
                    "minimum": 1,
                    "pattern": "^[a-zA-Z]+((_[a-zA-Z]+)*|([a-zA-Z]+_)*|_)"
                },
                "flanged": {
                    "type": "boolean"
                },
                "version": {
                    "type": "string",
                    "maximum": 64,
                    "minimum": 1
                },
                "colors": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/color"
                    }
                }
            }
        }
    },  

    "anyOf": [
        { "$ref": "#/definitions/baseWidget" },
        { "$ref": "#/definitions/bentWidget" },
        { "$ref": "#/definitions/highPowerWidget" }
    ]
}

我想测试它,所以我把它写到一个文件中:

{
    "type": "highPowerWidget",
    "title": "foobar",
    "version": "foo"
}

然后我在 shell 上运行 ajv

$ ajv -s widgetSchema.json -d widget-highPower.json 
widget-highPower.json valid

它告诉我它是有效的,这是不正确的,highPowerWidget 必须具有 power 属性,以及“继承”的 version 和 colors 属性。

我可以通过删除 anyOf 部分并输入如下内容来测试我的个人架构:

"properties": {
    "testObject": {
        "type": "object",
        "oneOf": [
            { "$ref": "#/definitions/baseWidget" },
            { "$ref": "#/definitions/bentWidget" },
            { "$ref": "#/definitions/highPowerWidget" }
        ]
    }
},
"required": [ "testObject" ]

并验证此 JSON:

{
   "testObject": {
        "type" : "highPowerWidget",
        "title" : "title",
        "version" : "baz",
        "colors" : [ "red", "green", "blue"],
        "flanged" : true
   }

}

但这似乎是错误的,原因有两个。

  1. 我不应该有一个“testObject”属性
  2. oneOf 仅在我列出单行时才有效,使用多行验证任何内容。

我认为我对如何编写或至少测试我的架构有一个基本的误解。我的目标是拥有一组全部验证的对象,以及一组全部失败的文件。这样我就可以对我的架构进行单元测试。

【问题讨论】:

  • power 不是 highPowerWidget 的必需属性,因此可以省略
  • 不错,但事实并非如此。 (我从我的实际工作中创建了“小部件”模式来保护我无法谈论的东西。你是对的,但 highPowerWidget 也应该有颜色,但它没有。另外,当我添加 required 到 highPower 时仍在验证...
  • (添加缺少必填)
  • 啊,但我缺少 '"required": ["power", "baseWidget"],' -- 这看起来很有希望......
  • 无效..

标签: jsonschema


【解决方案1】:

您的架构有效。正如所写,这将是一个有效的 highPowerWidget:

{
    "power": 150,
     "baseWidget":{
        "title": "SuperHighPower",
        "flanged":true,
        "version": "version 1",
        "colors":["blue"]
     }   
}

我认为误解是JSONSchema不支持OO style inheritance

相反,此架构本质上是要求 highPowerWidget 或 bentWidget 上的“baseWidget”属性。 Here's a sandbox plnkr 对于 AJV,您可以使用它进行测试。

编辑:想一想,您可以从bentWidget 和highPowerWidget 中删除baseWidget 属性,而是将"allOf":[{"$ref":"#/definitions/baseWidget"}] 添加到每个子小部件中。这将要求他们通过 baseWidget 的模式。所以你的架构是:

{
  "id": "http://schema.acme.com/widgets",
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "bentWidget": {
      "type": "object",
      "required": ["angle"],
      "properties": {
        "angle": {
          "type": "number",
          "minimum": 0,
          "maximum": 90
        }
      },
      allOf: [{
        "$ref": "#/definitions/baseWidget"
      }]
    },
    "highPowerWidget": {
      "type": "object",
      "required": ["power"],
      "properties": {
        "power": {
          "type": "number",
          "minimum": 101,
          "maximum": 200
        }
      },
      allOf: [{
        "$ref": "#/definitions/baseWidget"
      }]
    },
    "color": {
      "description": "the color of a widget",
      "type": "string"
    },
    "baseWidget": {
      "description": "The base type for a widget",
      "type": "object",
      "required": [
        "title",
        "version",
        "colors"
      ],
      "properties": {
        "title": {
          "type": "string",
          "maximum": 100,
          "minimum": 1,
          "pattern": "^[a-zA-Z]+((_[a-zA-Z]+)*|([a-zA-Z]+_)*|_)"
        },
        "flanged": {
          "type": "boolean"
        },
        "version": {
          "type": "string",
          "maximum": 64,
          "minimum": 1
        },
        "colors": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/color"
          }
        }
      }
    }
  },

  "anyOf": [{
    "$ref": "#/definitions/baseWidget"
  }, {
    "$ref": "#/definitions/bentWidget"
  }, {
    "$ref": "#/definitions/highPowerWidget"
  }]
}

【讨论】:

  • 抱歉回复慢。我离开了,然后工作笔记本电脑就死了。我现在正在看这个。看起来很有前途!
  • 这种方法的问题是很难找到没有经过schema验证的JSON数据,这样不好。例如,将“flanged”设置为字符串“true”,它仍然有效。我们已经完全失去了这种类型的感觉。我将尝试放入一个包含对象,该对象指定一个类型化的属性,应该这样做。
  • @PaulCezanne,我添加了一个可能的替代方案,使其更具洞察力
  • @PaulCezanne,抱歉我看错了最后一条评论。根据我链接到法兰的 ajv 沙箱:“true”不使用修改后的架构进行验证。它应该无法通过布尔类型检查。
【解决方案2】:

这里的问题是您实际上没有为"type" 字段声明架构。您的架构中没有任何内容表明具有 "type": "highPoweredWidget" 的实例需要匹配 "#/definitions/highPoweredWidget" 架构。 "definitions" 下的模式名称仅用于为"$ref" 定位它们。它们实际上并不直接用于验证。

由于您使用的是draft-06,您可以使用"const" 关键字来实现此目的。在上一个答案的基础上,我应该可以:

{
  "id": "http://schema.acme.com/widgets",
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "bentWidget": {
      "type": "object",
      "required": ["angle"],
      "properties": {
        "type": {"const": "bentWidget"},
        "angle": {
          "type": "number",
          "minimum": 0,
          "maximum": 90
        }
      },
      allOf: [{
        "$ref": "#/definitions/baseWidget"
      }]
    },
    "highPowerWidget": {
      "type": "object",
      "required": ["power"],
      "properties": {
        "type": {"const": "highPowerWidget"},
        "power": {
          "type": "number",
          "minimum": 101,
          "maximum": 200
        }
      },
      allOf: [{
        "$ref": "#/definitions/baseWidget"
      }]
    },
    "color": {
      "description": "the color of a widget",
      "type": "string"
    },
    "baseWidget": {
      "description": "The base type for a widget",
      "type": "object",
      "required": [
        "title",
        "version",
        "colors"
      ],
      "properties": {
        "title": {
          "type": "string",
          "maximum": 100,
          "minimum": 1,
          "pattern": "^[a-zA-Z]+((_[a-zA-Z]+)*|([a-zA-Z]+_)*|_)"
        },
        "flanged": {
          "type": "boolean"
        },
        "version": {
          "type": "string",
          "maximum": 64,
          "minimum": 1
        },
        "colors": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/color"
          }
        }
      }
    }
  },

  "anyOf": [{
    "$ref": "#/definitions/baseWidget"
  }, {
    "$ref": "#/definitions/bentWidget"
  }, {
    "$ref": "#/definitions/highPowerWidget"
  }]
}

这将确保如果您的 instance 具有 "type": "highPowerWidget",那么它将具有“power”属性。

我没有为“baseWidget”添加"const" 类型字段,因此它将匹配任何类型,据我所知,这似乎是正确的。

请注意,在 draft-07(周一发布,我认为受 ajv 测试版支持)中,您可以使用 "if" "then""else" 关键字来使其更加明确。

【讨论】:

    猜你喜欢
    • 2020-12-01
    • 1970-01-01
    • 2020-02-05
    • 2021-04-18
    • 1970-01-01
    • 2019-10-18
    • 2015-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多