JSON scema question on additionalProperties and required - json

I ran into this situation recently and would like to check my understanding, with a JSON (draft-7) schema.
additionalProperties is set to false, which means every property in our JSON object MUST be listed in the properties array.
the required array contains category, which is not in the properties array.
{
"$schema": "https://json-schema.org/draft-07/schema#",
"$id": "/my-schema-1.0.0",
"description": "My schema",
"type": "object",
"additionalProperties": false,
"properties": {
"value": {
"description": "The value.",
"type": "number"
}
},
"required": [
"value",
"category"
]
}
However, whenever i try to validate that my schema is valid, multiple validators say that it is.
But then i don't think you can create an object that would ever validate successfully against this schema.
I don't see anything within the JSON spec that mentions this conflict. Is anyone able to shed any light on this?

Related

Is there a Json schema validation implementation give all the missing required fields?

Normally, when validate a complicated json object, if an embedded field is required but the parent which is also required is missing, a validator only give the result saying the parent is required.
Wondering if there is a way (an implementation of json schema validator) to find all the mandatory fields (in the leaves of a json object) by applying a json schema validation?
Using https://www.jsonschemavalidator.net/
With schema
{
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "object",
"required": [
"firstName",
"secondName"
],
"properties": {
"firstName": {
"type": "string"
},
"secondName": {
"type": "string"
}
}
}
}
}
To validate an empty json object {}.
Can only get one error Message:
Required properties are missing from object: name.
Schema path: #/required
Can a validator give all the required fields including first and second names back in the error message?

Reusing JSON subschema

I am needing to use a sub schema multiple times in my JSON file, but haven't been able to figure out the correct way to structure the schema file such that I am able to get the schema validation on all the sub properties instead of just the property that I list in the schema file.
This question here was getting at a similar question, but the answer didn't make much sense/I wasn't sure if or how I could use the same method here. Am I thinking too much in the OOP mindset with multiple instances of a single class?
Here is more or less what I am trying to do
{
"Object1": {
"Title": "Some Title",
"Description": "Some Description"
},
"Object2": {
"Title": "Another title",
"Description": "Another Description"
}
// unknown number of objects but each object should have the same sub schema
}
Here is what I have thus far
{
"$id": "http://example.com/example.json",
"$schema": "http://json-schema.org/draft-07/schema",
"required": [
"Object1"
],
"title": "The root schema",
"type": "object",
"properties": {
"Object1": {
"required": [
"Title",
"Description"
],
"title": "The Reusable Object schema",
"type": "object",
"properties": {
"Title": {
"title": "The Title schema",
"type": "string"
},
"Description": {
"title": "The Description schema",
"type": "string"
}
},
"additionalProperties": false
}
},
"additionalProperties": true
}
If all values of the object should follow the schema, the solution is quite simple.
First, you have to remember how additionalProperties works...
The value of "additionalProperties" MUST be a valid JSON Schema.
This keyword determines how child instances validate for objects,
and does not directly validate the immediate instance itself.
Validation with "additionalProperties" applies only to the child
values of instance names that do not match any names in "properties",
and do not match any regular expression in "patternProperties".
For all such properties, validation succeeds if the child instance
validates against the "additionalProperties" schema.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.5.6
So, now we know that additionalProperties takes a JSON Schema, and not just booleans (booleans are valid JSON Schema), the solution might be a little obvious.
Remove the outermost additionalPropertie, rename properties to additionalProperties, and remove the key Object1 and object braces.
The result is the following...
...
"title": "The root schema",
"type": "object",
"additionalProperties": {
"required": [
"Title",
"Description"
],
...
Live demo: https://jsonschema.dev/s/pqwCc
I don't know what you would want to do with the outer most required though. I guess remove it, as you don't know in advance what the keys will be.
Maybe you want to use minProperties to make sure there is at least one?

Apply required field to referenced JSON data schema

I have the following use-case I try to solve with JSON schemas.
I have a generic JSON data schema for, for example, a user. Here is an example of the user.schema.json file.
{
"type": "object",
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"email": {
"type": "string",
"minLength": 1
},
"locale": {
"type": "string",
"minLength": 1
},
"active": {
"type": "boolean",
"default": true
},
"password": {
"type": "string",
"minLength": 8
},
"roles": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
}
}
}
Now I have 2 different kinds of requests:
- POST: Add a user
- PATCH: Update user data.
In 1 case, I can send this data structure, with 3 required fields, while in case of a patch each field is optional.
So I get the post request file: post-user.schema.json:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "user.schema.json",
"required": [
"name",
"password",
"email"
]
}
And for my patch (path-user.schema.json:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "user.schema.json"
}
Now the issue that I am having is that my POST schema also marks a user like:
{
"name": "NoPassword",
"email": "nopassword#moba.nl",
"roles": []
}
Which is missing the required password field, as a valid JSON schema.
Apparently, this is not the way to assign required fields to a referenced data structure. I have tried to use google to see what I can find on the subject regarding this using searches like:
[ how to assign required field to referenced schema's ]
and I tried to obtain this info from the documentation.
I have no luck.
My questions now are:
A. Is it possible to assign required fields to a $referenced json schema data object.
B. If this is possible how to do it
C. If this is not possible, what would be a good way to approach this.
Any help is much appreciated.
Using $ref results in all other properties in the object being ignored, so you need to wrap your use of $ref.
Let's take a look at the spec:
An object schema with a "$ref" property MUST be interpreted as a
"$ref" reference. The value of the "$ref" property MUST be a URI
Reference. Resolved against the current URI base, it identifies the
URI of a schema to use. All other properties in a "$ref" object MUST
be ignored.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-01#section-8.3
Then consider the schema you included in your question:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "user.schema.json",
"required": [
"name",
"password",
"email"
]
}
Reading the spec, you can see why required will be ignored.
Originally $ref was only designed to replace a WHOLE object, not ADD to the conditions for the object.
What you want is for multiple schemas to be applied to the instance. To do this, you use allOf.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{
"$ref": "user.schema.json"
},
{
"required": [
"name",
"password",
"email"
]
}
]
}
I loaded this schema into a demo for you to test at https://jsonschema.dev - although it doesn't support references yet, so I transcluded the reference, but the validation will work the same.
From draft-8 onwards, $ref will behave as you expect, as it becomes an applicator keyword rather than a keyword with special behaviours, meaning other keywords in the same object will not need to be ignored.

JSON schema - support regular expression for field

I want to use the following library gojsonschema to validate json structure,
Currenlty I've two questions to the example below
https://github.com/xeipuuv/gojsonschema
what is the #/definitions/.... and what is the purpose of it?
the name should have the following:
{required: true, unique: true, pattern: '/^[A-Za-z0-9_\-\.]+$/'}
The unique is that if I've another name filed in the schema it should be unique, How can I validate it with jsonschema?
var schema = `
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"name": ...
"properties": {
"username": {"$ref": "#/definitions/name"},
update
what I found is this
https://spacetelescope.github.io/understanding-json-schema/reference/regular_expressions.html
But how should I check it inside the json i've provided
should It be like this
var schema = `
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"name": {
"type": "object",
"pattern":'/^[A-Za-z0-9_\-\.]+$/'
}
"properties": {
"username": {"$ref": "#/definitions/name"},
https://datatracker.ietf.org/doc/draft-handrews-json-schema-validation/?include_text=1
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"username": {
"type": "array",
"items": {
"type": "string",
"pattern": "/^[A-Za-z0-9_\-\.]+$/"
},
"uniqueItems": true
}
},
"required": [
"username"
]
}
1: The "definitions" keywords provides a standardized location for
schema authors to inline re-usable JSON Schemas into a more general
schema. The keyword does not directly affect the validation result.
This keyword's value MUST be an object. Each member value of this
object MUST be a valid JSON Schema.
As an example, here is a schema describing an array of positive
integers, where the positive integer constraint is a subschema in
"definitions":
{
"type": "array",
"items": { "$ref": "#/definitions/positiveInteger" },
"definitions": {
"positiveInteger": {
"type": "integer",
"exclusiveMinimum": 0
}
}
}
2: uniqueItems
The value of this keyword MUST be a boolean.
If this keyword has boolean value false, the instance validates
successfully. If it has boolean value true, the instance validates
successfully if all of its elements are unique.
Omitting this keyword has the same behavior as a value of false.
required
The value of this keyword MUST be an array. Elements of this array,
if any, MUST be strings, and MUST be unique.
An object instance is valid against this keyword if every item in the
array is the name of a property in the instance.
Omitting this keyword has the same behavior as an empty array.
properties
{
"type": "object",
"properties": {
"progBinaryName": {
"type": "string",
"pattern": "^[A-Za-z0-9 -_]+_Prog\\.(exe|EXE)$"
}
}
}
The value of "properties" MUST be an object. Each value of this
object MUST be a valid JSON Schema.
This keyword determines how child instances validate for objects, and
does not directly validate the immediate instance itself.
Validation succeeds if, for each name that appears in both the
instance and as a name within this keyword's value, the child
instance for that name successfully validates against the
corresponding schema.
Omitting this keyword has the same behavior as an empty object.
#/definitions/name is an internal reference to another schema. The document should have section that looks like the following that is being referenced:
"definitions": {
"name": {
...
}
}
JSON schema does not have a unique validator. There is a uniqueItems validator that can be used with arrays but I don't think that is what you are looking for.

Compare object property to validate json schema in same object

I have a very simple object like so:
{
"title": "A registration form",
"description": "A simple form example.",
"type": "object",
"required": [
"firstName",
"lastName"
],
"properties": {
"firstName": {
"type": "string",
"title": "First name"
},
"lastName": {
"type": "string",
"title": "Last name",
"minLength": "{'$ref': '/properties/firstName'}"
},
}
On the property of LastName I would like to compare a value with a value of the property next to it. I am actually comparing integers so in actuality my real world example is even easier, just minimum and maximum.
I looked at the json schema spec here and it seemed like this should be doable, and have tried using relative paths and the $ref object.
Is this not possible?
The reference is here: https://www.rfc-editor.org/rfc/rfc6901
I am using react-jsonschema-form but I don't see where that would effect this.
There are a few of reasons why this doesn't work. The primary reason is that $ref refers to the schema, not the data being validated. There was talk of adding a $data keyword to JSON Schema that would allow referencing the instance data, but I don't think that will even happen.