How can i define a single, unique Key-Valuepair in JsonSchema? - json

The Schema should allow only the following constellation: {"status":"nok"}.
The Key must always be "status" and the value should allow "ok","nok","inProgress"
No differen or additional objects,... should be allowed
I have tried this:
{
"description": "blabla",
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ok",
"inProgress",
"nok"
],
"required": true,
"additionalItems": false
}
},
"required": true,
"additionalProperties": false
}
This works, but this scheme allows that i can send the same key/value pair twice like {"status":"nok","status":"nok"}
I would be also happy, if it would work without this "object"-container that i'm using, because to reduce overhead.
Maybe someone knows a solution, thanks

There is a more fundamental issue with that input:
{"status":"nok","status":"nok"}
mainly: that input is not valid JSON. RFC 4627, section 2.2, explicitly states that "The names within an object SHOULD be unique". And in your case, they are not.
Which means the JSON parser you use can do whatever it wants to with such an input. Some JSON APIs will grab whatever value they come upon first, other parsers will grab the last value they read, others will even coalesce values -- none of this is illegal as per the RFC.
In essence: given such input, you cannot guarantee what the output of the JSON parser will be; and as such, you cannot guarantee JSON Schema validation of such an input either.

Related

Why are booleans valid JSON schemas?

I'm looking at JSON schema's meta schemas and according to the Core/Validation Dialect meta-schema the JSON true and false are valid JSON schemas. What is the point of this?
You can see that they validate properly here.
It's true that a boolean schema, in its entirety, is not terribly useful, except perhaps as a placeholder ("in the future, we will have a more defined data structure; in the meantime, all values are acceptable"). But schemas can also contain schemas, and then we can start to express more meaningful things.
Consider describing data thusly:
the top level of the data must be an object.
the object must include the properties "alpha" and "beta".
the value of "alpha" must be a string.
the value of "beta" can be anything.
the property "gamma" may exist, and its value can be anything.
the property "epsilon" must not be present.
if there any other properties present, they must be numbers.
We would define the JSON schema like this:
{
"type": "object",
"required": ["alpha", "beta"],
"properties": {
"alpha": {
"type": "string"
},
"beta": true,
"gamma": true,
"epsilon": false,
},
"additionalProperties": {
"type": "number"
}
}
Now, as you can see, under the "properties" and "additionalProperties" keywords we have several subschemas. Some of the subschemas contain more keywords ("type" in this case), but some of the subschemas are just plain old booleans. They're conveying something of meaning: "this condition is always valid" or "this condition is always invalid".

Constraining the key in JSON schema

I would like to put constraints the key in a JSON document, using JSON schema. For example, I may have a JSON document that looks like this:
{
"id": 1,
"name": "a green door",
"price": 12.50,
"tags": ["home", "green"]
}
I don't care about which particular keys are being used, but I'd like to enforce in the schema that no key is longer than a certain number of characters; let's say 4 characters for the sake of argument. The example above would then fail schema validation, because "price" is 5 characters long.
I know how to validate the length of the value -- here, I care about the key.
You can use patternProperties to restrict property names to those that match a regular expression. In the case of your example, it might look like this:
{ "$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^.{1,4}$": {}
}
}
Note "additionalProperties": false is necessary as well.

Key values of 'key' and 'type' in json schema

I am given to understand that the words type and id are reserved words in json schema. Is there any way to set these as keys in json schema? Here is an example of what I am trying to do.
"id": {
"type": "string"
},
"featureType": {
"type": "string"
},
"type": {
"type": "string"
}
I have tried validating this using a number of tools (including here). Googling around yields no suggestions either. Any help much appreciated. Cheers!
The snippet you pasted above will most probably work. "type" and "id" are reserved keys, but they have special meaning only in case their corresponding value is a string. Since the values are objects in your case, there is no problem. I'm not 100% sure if the json schema spec explicitly states this, but this is how implementations work usually.

how to give empty for email in json

I need to construct json schema for email which will accept either empty or email format.
I used as follows
"emailID": {
"type": "string",
"required": false,
"format": "(^$)|email"
}
But it is not validating email id is in right format or not.
even if email is simply A or * it is accepting.
But if I remove (^$) in format it is validating perfectly
how to put both conditions
First of all: this is a draft v3 schema; it is invalid against the current draft because of your required.
Then, your requirements are quite strange: either you say that the object member is not required, or if it is present it can either be an empty string or a valid email? Something is wrong somewhere.
Not that this is not doable; it is:
"emailID": {
"type": "string",
"oneOf": [
{ "enum": [ "" ] },
{ "format": "email" }
]
}
But given your "sloppy" set of constraints I am of the opinion that something is wrong somewhere.

Json Schema, take into account unspecified properties

Is there is any ways to get heads ups about properties which are not described by schema into the standard. For example this schema:
{
"description": "foo and bar",
"type": "object",
"properties": {
"foo": {
"type": "number"
},
"bar": {
"type": "string",
"enum": [
"a",
"b",
"c"
]
}
}
}
Will pass this JSON:
{
"foo": 12345,
"bar": "a",
"baz": 12312
}
Although it has baz property which is not the part of schema.
UPD: As of now I'm using tv4 library.
Option 1: additionalProperties in the schema
If you want to explicitly constrained to the properties listed in a particular properties definition, then you can use additionalProperties: false. This will restrict data to only using properties defined in the nearby properties entry - in this case, "foo" and "bar".
However, use of additionalProperties impacts schema extension. If you (or someone else) extends this schema later (using allOf/$ref), then the data will still be subject to this schema - so will only be allowed to use "foo" and "bar", regardless of definitions elsewhere.
Option 2: banUnknownProperties flag in tv4
If the kind of complete lock-down is not desired, then you can use the banUnknownProperties flag in tv4 (docs). Basically, after validation, any properties that were not accounted-for by any schemas are raised as errors.
It was designed for cases when extra properties (including future variations/extensions) are theoretically allowed in the data format, but you want (for testing/warning purposes) to be alerted when extra properties show up where you're not expecting them.