JSON-Schema,基本样本不验证

时间:2017-11-15 18:35:25

标签: jsonschema

我有以下示例架构:

{
    "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属性,以及“继承”版本和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,使用多行验证任何内容。
  3. 我认为我对如何编写或至少测试我的模式有一个基本的误解。我的目标是拥有一组全部验证的对象,以及一组全部失败的文件。这样我就可以对我的架构进行单元测试。

2 个答案:

答案 0 :(得分:2)

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

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

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

相反,这个架构实际上是在highPowerWidget或bentWidget上要求“baseWidget”属性。 AJV Here's a sandbox plnkr你可以用它来测试它。

编辑:只是想一想,你可以完成这个从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"
  }]
}

答案 1 :(得分: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"
  }]
}

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

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

请注意,在草案07(周一发布,我认为支持ajv的beta版)中,您可以使用"if" "then""else"个关键字来更明确地说明这一点