JSON Schema v7: formatMinimum & formatMaximum validate everything - jsonschema

I am using ajv json schema library (v7) and trying to validate a date based on some value. It looks pretty straightforward with using formatMinimum/formatMaximum but it seems that every date is validated when using these keywords
Here's my schema
"some-date": {
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"value": {
"type": "string",
"format": "date-time",
"formatMinimum": "2021-03-10T14:25:00.000Z"
}
}
}
}
}
Here's the json:
{
"some-date": {
"data": {
"value": "2011-03-10T14:25:00.000Z"
}
}
}
Here's how I am validating:
const ajv = new Ajv({allErrors: true})
require('ajv-formats')(ajv)
require('ajv-errors')(ajv)
require('ajv-keywords')(ajv)
const validate = ajv.validate(mySchema)
const isValid = validate(myJSON)
I've tried it on JSONSchemalint and it validates the above json with the given schema. Also, I have tried with several dates and it validates everything.
Please let me know if I am missing something.
Thanks

I'm not sure where you're getting formatMinimum and formatMaximum from, but they are not standard keywords in the JSON Schema specification, under any version. Are they documented as supported keywords in the implementation that you are using?

Related

Using $vars within json schema $ref is undefined

While following the documentation for using variables in json schema I noticed the following example fails. It looks like the number-type doesn't get stored as a variable and cannot be read.
{
"$id": "http://example.com/number#",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["natural", "integer"]
},
"value": {
"$ref": "#/definitions/{+number-type}",
"$vars": {
"number-type": {"$ref": "1/type"}
}
}
},
"required": ["type", "value"],
"definitions": {
"natural": {
"type": "integer",
"minimum": 0
},
"integer": {
"type": "integer"
}
}
}
results in
Could not find a definition for #/definitions/{+number-type}
tl;dr $vars is not a JSON Schema keyword. It is an implementation specific extension.
The documentation you link to is not JSON Schema. It is documentation for a specific library which adds a preprocessing step to its JSON Schema processing model.
As such, this would only ever work when using that library, and would not create an interoperable or reuseable JSON Schema, if that's a consideration.
If you are using that library specifically, it sounds like a bug, and you should file an Issue in the appropriate repo. As you haven't provided any code, I can't tell what implementation you are using, so I can't be sure on that.

JSON Schema: Can I use "if" deeper than root of schema?

I want to validate objects like this
{
type: "user",
data: {id: 1},
}
and
{
type: "account",
data: {uuid: "xxxx"},
}
I thought I can write schema like this
{
type: "object",
properties: {
type: {enum: ["user", "account"]},
data: {
"if": {properties: {type: {const: "user"}}},
"then": {
type: "object",
properties: {
id: {type: "number"}
}
},
"else": {
type: "object",
properties: {
uuid: {type: "string"}
}
},
}
}
}
but it looks like I can't refer to root type field from context of data field. So I have two questions. Can I use if deeper than root? If I can then how to refer to parent or root object from nested object? I'm using node ajv for validation.
You're correct, you cannot apply validation to a different part of your data than where your subschems is being applied. Let me explain a little.
The first thing that happens when processing a JSON Schema is the Schema as a whole is "applied" to the instance as a whole.
properties is an applicator keyword, in that it doesn't assert any validation rules by itself. The VALUES of a properties object are subschemas (which are Schemas in their own right) which are APPLIED to the instance location value when the associated KEY matches.
To give you an exanple, in your Schema, the subschema at properties > type is applied to instance location type, which means the VALUE of the object key type. If type didn't exist in your data, the subschema in your Schema wouldn't do anything (it wouldn't be applied anywhere).
This is broadly the processing model of a Schema against an instance. Hopefully this explains why you can't work in the way you're expecting. However it's still possible to achive what you want.
then and else are conditional applicator keywords, and so need to be applied following the same model.
What you need to do is use if, then, else at the top level, but have deep / nested application of the validation you want to do.
Here's a demo with a new Schema and instance
https://jsonschema.dev/s/sejHF
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"properties": {
"type": {
"enum": [
"user",
"account"
]
},
"data": {}
},
"if": {
"properties": {
"type": {
"const": "user"
}
}
},
"then": {
"type": "object",
"properties": {
"data": {
"properties": {
"id": {
"type": "number"
}
}
}
}
},
"else": {
"type": "object",
"properties": {
"data": {
"properties": {
"uuid": {
"type": "string"
}
}
}
}
}
}
If you also want to make sure that id is present when type is user, then you also need to add required: ['id'] in the then subschema. (You'll need to do similar in the else clause if you want to check for uuid too.

How to enforce only one property value to true in an array (JSON Schema)

I am trying to have JSON validation based on the following input:
{
"elements":[
{
"..."
"isSelected": true
},
{
"..."
"isSelected": false
},
{
"..."
"isSelected": false
}
]
}
The input is going to be valid if and only if we have "isSelected" set to "true" (and all the rest set to "false"). Can't have "isSelected: true" more than once (and all the rest need to be "false").
Tried with the following:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"definitions": {
"element":{
"type": "object",
"properties": {
"isSelected": {
"type": "boolean"
}
}
}
},
"properties": {
"elements": {
"type": "array",
"items": {
"$ref": "#/definitions/element"
},
"oneOf": [
{
"isSelected": true
}
]
}
},
}
unfortunately I don't think this is possible with json schema draft 7. the newest draft (2019-09) features the maxContains keyword, which would be able to validate this, but tooling for this draft is sparse so far. I don't know the tooling you're using, but if you are able to use 2019-09, the schema for 'elements' would look something like:
{
"type": "array",
"contains": {
"properties": {
"isSelected": {"const": true}
}
},
"maxContains": 1
}
oneOf isn't what you're looking for, for this - it checks that one of a set of schemas validates against the instance, not whether one of a set of instances validates against a schema.
This is not currently supported, but you may be interested in this proposal which intends to add a keyword to support key-based item uniqueness. It's not exactly the same, but I think it's related.

Modify data using AJV for Json Schema

I'm using AJV (Another Json schema validator) on NodeJs.
I've the following schema
var schema = {
"$id": "testSchema.json",
"type": "object",
"$schema": "http://json-schema.org/draft-06/schema#",
"additionalProperties": false,
"properties": {
"userId": {
"type": "integer"
},
"userName": {
"type": "string"
},
"uniqueID": {
"type": "integer"
}
}
}
I need to overwrite unqiueID property by a value that I could somehow pass to Json schema or AJV.
I think the above can be done using AJV addKeyword method, tried using it but failed because I don't know how to manipulate (and return) data value from AJV custom keywords.
Is possible to modify data with AJV ? or are there any other possible ways to do it??
Thank you!
You can create a custom keyword with function that will do whatever your want to data.
var Ajv = require('ajv');
var ajv = new Ajv({allErrors: true});
ajv.addKeyword('my_id_rewrite', {
type: 'object',
compile: function (sch, parentSchema) {
return function (data) {
console.log(data)
data['my_id']=parentSchema.my_id_rewrite;
return true;
}
}
});
var schema = { "my_id_rewrite": 2 };
var validate = ajv.compile(schema);
o = {"my_id":1}
console.log(validate(o)); // true
console.log(o); // Object {my_id: 2}
https://runkit.com/embed/cxg0vwqazre3

Dredd (gavel) : Begin a Json Schema with an array (bug ?)

I am using Markdown for Generate documentation (aglio), generate mocks (api-mock) and check the integrity constraints (dredd).
With Dredd, no problem for check an object, no problem for PUT or POST, but I have a problem with lists.
My lists are arrays, but when I write this schema :
{
"title": "Videos List",
"type": "array",
"items": {
"type":"object",
"required":false,
"properties": {
"id": {
"type": "string",
"required": true
}
},
"required": true
}
}
I get same error all the time: body: JSON schema is not valid! invalid type: object (expected [object Object]/array) at path "/items"
I've tried, again and again, 3 hours, but I failed.
Please help!
PS : sorry for my English, I'm french.
Yes, your data is correct again that schema.
It might be a specific problem of the validator your are using (you did not mention which). You can try to enclose your data with {}. I guess it is expecting allways a JSON like this:
{
[
{
"id": "ninon-retrouve-rudy",
"title": "Ninon retrouve Rudy edited"
},
{
"id": "ninon-retrouve-rudy-1",
"title": "Ninon retrouve Rudy"
}
]
}
Be aware also that your are using Draft03 of Json-schema. I suggest you to use Draft04 (your validator might be obsolete).