Could you help me, how I can validate "keys"(ex. "1","2","3") of list items in following json:
{
"list" : {
"1" : {
"element1" : "1",
"element2" : "2"
},
"2" : {
"element1" : "1",
"element2" : "2"
},
....
"512" : {
"element1" : "1",
"element2" : "2"
}
}
}
Please give me common examples to validate keys in json, too.
JSON Schema has three ways to constraint the property names of an object.
properties
The properties keyword allows you to set an exact match for property names.
{
"type": "object",
"properties": {
"1": { ... },
"2": { ... },
...
}
}
patternProperties
The patternProperties keyword constrains any property name that matches a regular expression to validate against a given schema.
{
"type": "object",
"patternProperties": {
"[1-9][0-9]*": { ... }
}
}
propertyNames
The propertyNames keyword constraints property names to match the given schema.
{
"type": "object",
"propertyNames": {
"pattern": "[1-9][0-9]*"
}
}
Edit 12-19-2018 Improve answer, add missing patternProperties, add new (since original answer) option propertyNames.
Related
I want to create several json schemas for different scenarios.
For scenario 1 I would like to specify that:
a) The property "draftenabled" must have the value true.
b) the property "draftenabled" does exist.
I have checked this post
Validating Mandatory String values in JSON Schema
and tried the following
I tried to validate this json
{
"$schema": "./test-schema.json",
"draftenabled": false,
"prefix": "hugo"
}
with this schema test-schema.json that I had created in Visual Studio Code.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"$schema": {
"type": "string"
},
"draftenabled": {
"type": "boolean"
},
"prefix": {
"type": "string"
}
},
"additionalItems": false,
"contains": {
"properties": {
"draftenabled": {
"const": true
}
},
"required": [
"draftenabled"
]
}
}
I would have expected an error since the value for draftenabled is false rather than true.
It looks like there is some confusion around how the keywords apply to instances (data) of different types.
properties only applies to objects
additionalItems and contains only apply to arrays
Since your instance is an object, additionalItems and contains will be ignored.
Based on your description of what you want, I would do something like the following:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"$schema": {
"type": "string"
},
"draftenabled": {
"const": "true"
},
"prefix": {
"type": "string"
}
},
"required": [
"draftenabled"
]
}
This moves the definitions you have in the contains into the main schema. You got that bit right, just in the wrong place.
You also mention that this is a "scenario 1." If there are other scenarios, I suggest creating schemas like this for each scenario then wrapping all of them together in a oneOf or anyOf:
{
"oneOf": [
{ <scenario 1> },
{ <scenario 2> },
...
]
}
Say I have the following JSON that I'd like validated.
[
{
"UpStatus":"Closed"
},
{
"UpStatus":"Open"
}
]
I want the json to pass validation only if there is at least one 'UpStatus' in the array defined to either 'Open' or 'Locked'.
If 'UpStatus' is not found as set to 'Open' or 'Locked' in the array, and is set to something else that is arbitrary say "Closed", I want the validation to fail.
I tinkered around with anyOf and came up with the following schema.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items": [
{
"type": "object",
"properties": {
"UpStatus": {
"type": "string"
}
},
"minItems": 1,
"anyOf": [
{
"properties": {
"UpStatus": {
"const": "Open"
}
},
"required": [
"UpStatus"
]
},
{
"properties": {
"UpStatus": {
"const": "Locked"
}
},
"required": [
"UpStatus"
]
}
]
}
]
}
The above does not work correctly as it allows the following to pass which I thought it should fail to validate.
[
{
"UpStatus": "Closed"
},
{
"UpStatus": "Closed"
}
]
I played with the json schema for a long time and looked at examples and read some docs but could not get it to work. Any help is appreciated. Thank you.
In your schema above, you put the "minItems" keyword inside "items", which does nothing -- it needs to be adjacent to "items". But using "items" also means that all items must match, not just one.
Instead, use "contains":
{
"type: "array",
"contains": {
"type": "object",
"required": ["UpStatus"],
"properties": {
"UpStatus": {
"enum": ["Open","Locked"],
}
}
}
}
Translation: the data must be an array, where at least one element must be an object, which has the property "UpStatus" with value either "Open" or "Locked".
You may want all items in the array to conform to something specific, in which case you use "items" to specify that. The difference between "items" and "contains" is that the "items" schema must match all items, whereas the "contains" schema only has to match one.
HOWEVER, "contains" is not available in the draft 4 version of the spec. Is there any chance you can upgrade? There is a list of implementations in various languages here. Alternatively, you can simulate the "contains" keyword with "not": { "items": { "not": { ... schema ... } } } (courtesy Jason Desrosiers).
addendum: When I evaluate your schema and data, it does not pass, but rather produces these errors, so perhaps your implementation is buggy (or you mispasted something):
{
"errors" : [
{
"error" : "value does not match",
"instanceLocation" : "/0/UpStatus",
"keywordLocation" : "/items/0/anyOf/0/properties/UpStatus/const"
},
{
"error" : "not all properties are valid",
"instanceLocation" : "/0",
"keywordLocation" : "/items/0/anyOf/0/properties"
},
{
"error" : "value does not match",
"instanceLocation" : "/0/UpStatus",
"keywordLocation" : "/items/0/anyOf/1/properties/UpStatus/const"
},
{
"error" : "not all properties are valid",
"instanceLocation" : "/0",
"keywordLocation" : "/items/0/anyOf/1/properties"
},
{
"error" : "no subschemas are valid",
"instanceLocation" : "/0",
"keywordLocation" : "/items/0/anyOf"
},
{
"error" : "not all items are valid",
"instanceLocation" : "",
"keywordLocation" : "/items"
}
],
"valid" : false
}
How can I hint the type of embedded objects in JSON Schema, analogous to xsi:type in XML Schema?
Example schema document:
{
"type": "storeRequest",
"properties": {
"txid": {
"description": "Transaction ID to prevent double committing",
"type": "integer"
},
"objects": {
"description": "Objects to store",
"type": "array"
"items": {
"type": "object"
},
"minItems": 1,
"uniqueItems": true
},
},
"required": ["txid", "objects"]
}
This is a request the client sends to the server to store multiple objects in the database. Now how can I recursively validate the content of objects when it can contain more than one type of object. (Plymorphism, really).
There is not an equivalent to xsi:type in JSON-schema AFAIK.
Perhaps the most JSON-schema idiomatic way to hint the existence of types would be the explicit definition of types as schemas and referencing them through $ref:
{
"properties" : {
"wheels" : {
"type" : "array",
"items" : "$ref" : "#/definitions/wheel"
}
}
"definitions" : {
"wheel" : {
"type" : "object"
}
}
}
Another way could be to give a hint through enums :
{
"definitions" : {
"vehicle" : {
"properties" : {
"type" : {
"enum" : ["car", "bike", "plane"]
}
}
},
"plane" : {
"properties" : {
"type" : {
"enum" : "plane"
}
}
"allOf" : ["$ref" : "#/definitions/vehicle"]
}
}
}
Finally you can also add whatever tag you can process to a JSON-schema and follow your conventions.
Be aware that you are not going to find an equivalent translation between typical object oriented programming languages (java, C#) inheritance semantics and JSON-schema.
Consider the following JSON :
{
"1234abcd" : {
"model" : "civic"
"made" : "toyota"
"year" : "2014"
}
}
consider another JSON :
{
"efgh56789" : {
"model" : "civic"
"made" : "toyota"
"year" : "2014"
}
}
the outermost alphanumeric key will vary and required, if the key was fixed; let's say "identifier" then the schema was straightforward, however since the key-name is variable, we have to use patternProperties, how can I come up with a schema that captures these requirement for the outermost key:
property name (key) is variable
required
alphanumeric lowercase
using json-schema : https://github.com/ruby-json-schema/json-schema in ruby.
The best you can do to require properties when those properties are variable is to use minProperties and maxProperties. If you want to say there must be one and only one of these alphanumeric keys in your object, you can use the following schema. If you want to say there has to be at least one, you could just leave out maxProperties.
{
"type": "object",
"patternProperties": {
"^[a-z0-9]+$": {
"type": "object",
"properties": {
"model": { "type": "string" },
"make": { "type": "string" },
"year": { "type": "string" }
},
"required": ["model", "make", "year"]
}
},
"additionalProperties": false,
"maxProperties": 1,
"minProperties": 1
}
You may have to change the regular expression to fit your valid keys:
{
"patternProperties": {
"^[a-zA-Z0-9]*$":{
"properties": {
"model":{"type":"string"},
"made":{"type":"string"},
"year":{"type":"string"}
}
}
},
"additionalProperties":false
}
I have to validate JSONs that look like:
{
"propertyName1" : "value",
"propertyName2" : ["value1", "value2"],
"propertyName3" : { "operator1" : "value" },
"propertyName4" : { "operator2" : ["value1", "value2"] },
...
}
So the propertyName is an arbitrary key, and operators are defined.
I think I should use a schema like:
{
"id" : "urn:my_arbitrary_json#",
"type" : "object",
"required" : false,
"additionalProperties" : {
"id" : "urn:my_arbitrary_key#",
"type" : "object",
"required" : true,
"properties" : {
"operator1" : { ... },
"operator2" : { ... }
}
}
}
However, this schema lacks definition for propertyName1 and propertyName2 cases. I would like to define an array to validate different types of additionalProperties, but this is not correct according to specification. Is there any way to validate such a JSON?
If a given piece of data can be many different shapes, then you can use oneOf or anyOf. For instance here you could have:
{
"type" : "object",
"additionalProperties" : {
"oneOf": [
{... string ...},
{... array of strings ...},
...
]
}
}
Actually, because the options here are all distinct types, you can simply have multiple entries in type instead:
{
"type" : "object",
"additionalProperties" : {
"type": ["string", "array", "object"],
"items": {"type": "string", ...}, // constraints if it's an array
"properties": {...} // properties if it's an object
}
}