JSON-Schema, the base sample does not validate

I have the following example circuit:

{ "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 check it, so I write this to a file:

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

and then I run ajv on it from the shell

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

And he tells me that it is valid, and that is not true, for HighPowerWidget there must be a power property and a property of "inherited" and colors.

I was able to test my individual schemas by deleting the anyOf section and entering something like this:

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

and checking this json:

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

But this seems wrong for two reasons.

  • I do not need to have a testObject property
  • The oneOf function only worked when I enumerated a single line using several lines confirming something.

I think I have a basic misunderstanding of how I can write, or at least test my circuits. My goal is to have an array of objects that everyone checks, and a set of files that all fail. That way I can unit test my circuit.

+5
source share
2 answers

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

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

I think the misunderstanding is that JSONSchema does not support OO style inheritance .

Instead, this scheme basically queries the baseWidget property for either highPowerWidget or bentWidget. Here's the plnkr sandbox for AJV with which you can test it.

EDIT . Just thought about it, and you can accomplish this by removing the baseWidget property from bentWidget and highPowerWidget and instead add "allOf":[{"$ref":"#/definitions/baseWidget"}] to each of the moves. This will require them to skip the baseWidget scheme. So your circuit will 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" }] } 
+2
source

The problem is that you have not actually declared a schema for your "type" field. There is nothing in your schema that says that the instance with "type": "highPoweredWidget" should match the schema "#/definitions/highPoweredWidget" . The schema names in the "definitions" section are used only to find them for "$ref" . They are not actually used directly in validation.

Since you are using draft-06, you can use the "const" keyword to achieve this. Based on the previous answer, I should work as follows:

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

This ensures that if your instance has "type": "highPowerWidget" , then it will have the "power" property.

I have not added a field of type "const" to "baseWidget", so it will match any type that seems correct, as far as I can tell.

Note that in project-07 (published on Monday, and I think it is supported by the ajv beta build), you can use the keywords "if" "then" and "else" to make this more explicit.

+2
source

Source: https://habr.com/ru/post/1273409/


All Articles