Is there a way to enable a JSON schema property to be either a number or null
?
I am building an API which contains a heading
attribute. Can be a number between 0 (inclusive) and 360 (exclusive), or null, so the following inputs are OK:
{"heading": 5} {"heading": 0} {"heading": null} {"heading": 12} {"heading": 120} {"heading": null}
And the following inputs are erroneous:
{"heading": 360} {"heading": 360.1} {"heading": -5} {"heading": false} {"heading": "X"} {"heading": 1200} {"heading": false}
Addendum:
anyOf
is clearly the right answer. Adding the full schema for clarity.
{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "additionalProperties": false, "properties": { "heading": { "anyOf": [ {"type": "number"}, {"type": "null"} ] } } }
To include null values in the JSON output of the FOR JSON clause, specify the INCLUDE_NULL_VALUES option. If you don't specify the INCLUDE_NULL_VALUES option, the JSON output doesn't include properties for values that are null in the query results.
The simplest way to check if JSON is valid is to load the JSON into a JObject or JArray and then use the IsValid(JToken, JsonSchema) method with the JSON Schema. To get validation error messages, use the IsValid(JToken, JsonSchema, IList<String> ) or Validate(JToken, JsonSchema, ValidationEventHandler) overloads.
JSON Schema Validation: The JSON Schema Validation specification is the document that defines the valid ways to define validation constraints. This document also defines a set of keywords that can be used to specify validations for a JSON API.
In draft-04, you would use the anyOf directive:
{ "anyOf": [ { "type": "number", "minimum": 0, "maximum": 360, "exclusiveMaximum": true }, { "type": "null" } ] }
You could also use "type": ["number", "null"] as Adam suggests, but I think anyOf is cleaner (as long as you use a draft-04 implementation), and ties the minimum and maximum declaration to the number explicitly.
Disclaimer: I don't know anything about the python implementation, my answer is about json schema.
The trick is using a type array. Instead of:
"type": "number"
Use:
"type": ["number", "null"]
The following code enforces a number-or-null policy, plus numerical restrictions if the value is a number:
from jsonschema import validate from jsonschema.exceptions import ValidationError import json schema=json.loads("""{ "$schema": "http://json-schema.org/schema#", "description": "Schemas for heading: either a number within [0, 360) or null.", "title": "Tester for number-or-null schema", "properties": { "heading": { "type": ["number", "null"], "exclusiveMinimum": false, "exclusiveMaximum": true, "minimum": 0, "maximum": 360 } } }""") inputs = [ {"heading":5}, {"heading":0}, {"heading":360}, {"heading":360.1}, {"heading":-5},{"heading":None},{"heading":False},{"heading":"X"}, json.loads('''{"heading":12}'''),json.loads('''{"heading":120}'''), json.loads('''{"heading":1200}'''),json.loads('''{"heading":false}'''), json.loads('''{"heading":null}''') ] for input in inputs: print "%-30s" % json.dumps(input), try: validate(input, schema) print "OK" except ValidationError as e: print e.message
Which gives:
{"heading": 5} OK {"heading": 0} OK {"heading": 360} 360.0 is greater than or equal to the maximum of 360 {"heading": 360.1} 360.1 is greater than or equal to the maximum of 360 {"heading": -5} -5.0 is less than the minimum of 0 {"heading": null} OK {"heading": false} False is not of type u'number', u'null' {"heading": "X"} 'X' is not of type u'number', u'null' {"heading": 12} OK {"heading": 120} OK {"heading": 1200} 1200.0 is greater than or equal to the maximum of 360 {"heading": false} False is not of type u'number', u'null' {"heading": null} OK
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With