Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON-Schema, basic sample doesn't validate

Tags:

I have this following example schema:

{
    "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" }
    ]
}

and I want to test it, so I write this out to a file:

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

and then I run ajv on it from a shell

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

And it tells me that it is valid, which is incorrect, a highPowerWidget must have a power property, and the "inherited" version and colors property.

I was able to test my individual schemas by removing the anyOf section and putting in something like this:

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

and validating this JSON:

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

}

But this seems wrong for two reasons.

  1. I shouldn't have to have a "testObject" property
  2. The oneOf only worked when I listed a single line, using multiple lines validate anything.

I think I have a basic misunderstanding of how I can write, or at least test, my schemas. My goal is to have an array of objects that all validate, and a set of files which all fail. This way I can unit test my schema.

like image 663
Paul Cezanne Avatar asked Nov 15 '17 18:11

Paul Cezanne


1 Answers

Your schema is valid. As written this would be a valid highPowerWidget:

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

I think the misunderstanding is that JSONSchema doesn't support OO style inheritance.

Instead this schema is essentially asking for a "baseWidget" property on either the highPowerWidget or bentWidget. Here's a sandbox plnkr for AJV you can test it with.

EDIT: Just thought about it and you could accomplish this removing the baseWidget property from bentWidget and highPowerWidget and instead add "allOf":[{"$ref":"#/definitions/baseWidget"}] to each of the subwidgets. That would require them to pass baseWidget's schema. So your schema would be:

{
  "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"
  }]
}
like image 113
Roy Reiss Avatar answered Sep 22 '22 12:09

Roy Reiss