Required fields for properties within an array of objects schema definition - json

I have following schema definition. library is required. there can be many. so in that library object there are some other properties which is required. But though i use following code it is not validating. I mean book title is not required. title of the author is required.How can i fix this?
schema definition
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": ["library"],
"properties": {
"library": {
"type": "array",
"items": [
{"required":["title"],
"type": "object",
"properties": {
"title": {
"type": "string"
},
"author": {
"type": "string"
}
}
}
]
}}}
json input
{"library":[]
}
expected json input
{"library":[{"title":"Max"}]
}

I assume you want "json input" to fail.
If so, your problem is that you didn't describe a library with a book with missing title, Instead, your document says 'I am a library with no books'.
Failing JSON:
{"library":[{}]}
Alternately, if you want to probibit empty libraries: JSON Schema has a minLength property.

Your question is a little difficult to understand, but I noticed that you are using the tuple form of the items keyword. I'm sure that is not what you want. Try the following schema and I think it will behave the way you expect.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": ["library"],
"properties": {
"library": {
"type": "array",
"items": {
"required": ["title"],
"type": "object",
"properties": {
"title": {
"type": "string"
},
"author": {
"type": "string"
}
}
}
}
}
}

Related

JSON Schema: Additional properties false for embedded objects

I have a json schema with hundreds of objects, each containing other objects and so on...
I want all my json schema objects to have the option "additionalProperties" set to false, but it seems that I have to set it for each object in the json schema.
Is there any solution like setting "additionalProperties" to false only once for all objects including multiple level of embedded objects in the whole schema ?
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Modified JSON Schema draft v4 that includes the optional '$ref' and 'format'",
"type": "object",
"properties": {
"id": {
"type": "string"
},
"box": {
"type": "object",
"properties": {
"anotherBox": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
}
},
"title": {
"type": "string"
}
}
}
Thank you

JSON Schema reference resolution

I have a JSON schema that contains "$ref" tags and I am trying to get a version of the JSON schema that have the "$ref" tags resolved. I am only looking to resolve "$ref" from definition (tags) within the JSON Schema string (ie. not external resolution needed).
Is there a library that performs the resolution of the JSON Schema? (I am currently using org.everit.json.schema library, which is great, but I can't find how to do what I need).
For example, my original schema is:
{
"$id": "https://example.com/arrays.schema.json",
"description": "A representation of a person, company, organization, or place",
"title": "complex-schema",
"type": "object",
"properties": {
"fruits": {
"type": "array",
"items": {
"type": "string"
}
},
"vegetables": {
"type": "array",
"items": { "$ref": "#/$defs/veggie" }
}
},
"$defs": {
"veggie": {
"type": "object",
"required": [ "veggieName", "veggieLike" ],
"properties": {
"veggieName": {
"type": "string",
"description": "The name of the vegetable."
},
"veggieLike": {
"type": "boolean",
"description": "Do I like this vegetable?"
}
}
}
}
}
Which would resolve to something like this (notice that the "#defs/veggie" resolves to its definition inserted inline in the schema):
{
"$id": "https://example.com/arrays.schema.json",
"description": "A representation of a person, company, organization, or place",
"title": "complex-schema",
"type": "object",
"properties": {
"fruits": {
"type": "array",
"items": {
"type": "string"
}
},
"vegetables": {
"type": "array",
"items": {
"type": "object",
"required": [ "veggieName", "veggieLike" ],
"properties": {
"veggieName": {
"type": "string",
"description": "The name of the vegetable."
},
"veggieLike": {
"type": "boolean",
"description": "Do I like this vegetable?"
}
}
}
}
}
}
This isn't possible in the general sense, because:
the $ref might be recursive (i.e. reference itself again)
the keywords in the $ref might duplicate some of the keywords in the containing schema, which would cause some logic to be overwritten.
Why do you need to alter the schema in this way? Generally, a JSON Schema implementation will resolve the $refs automatically while evaluating the schema against provided data.

Json schema with keys as data

I have some hard time dealing with json schema.
Suppose this is initial simple json.
[
{
"Field1": 1,
"Description": "Default"
},
{
"Field1": 77,
"Description": "NonDefault"
}
]
And this is schema written which is valid
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {
"type": "object",
"properties": {
"Field1": {
"type": "integer"
},
"Description": {
"type": "string"
}
}
}
}
I wanted to change Json, to use "Field1" as key.
"Field1" is integer value.
I do not know values and how many Field1 there will be in json.
This is final JSON
{
"1": {
"Description": "Default"
},
"77": {
"Description": "NonDefault"
}
}
But how to write json-schema for this JSON?
TimRoberts' answer is almost there. What you want is to describe the item in the patternProperties subschema, similar to how you have items in your example schema.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"patternProperties": {
"^[0-9]*$": {
"type": "object",
"properties": {
"Description": { "type": "string" }
}
}
}
}
You can use "propertyNames" with a "pattern" element to create a regular expression to qualify your key names, instead of enumerating them all. I, personally, prefer your first layout.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"patternProperties": {
"^[0-9]*$": { "type": "string" }
}
}

Can a property of an allOf item contain a $ref to another allOf items definition?

Is "#/allOf/1/properties/body/properties/foo" a valid $ref?
As stated in this article which explains $ref usage, it looks like it should be.
However both AJV and https://www.jsonschemavalidator.net/ seem to disagree.
Trying with a plain JSON Pointer it definitely seems to be possible: https://repl.it/repls/WretchedSpiritedMammoth
This is the schema I'm testing with.
{
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"allOf": [
{
"$schema": "http://json-schema.org/draft-06/schema#",
"$id": "http:/example.org/example.schema.json",
"type": "object",
"properties": {
"type": {
"type": "string"
},
"body": {
"type": "object"
}
},
"required": [
"type",
"body"
]
},
{
"properties": {
"body": {
"$schema": "http://json-schema.org/draft-06/schema#",
"$id": "http://example.org/foo.schema.json",
"type": "object",
"properties": {
"foo": {
"type": "number",
"minimum": 1
},
"bar": {
"$ref": "#/allOf/1/properties/body/properties/foo"
}
},
"required": [
"foo",
"bar"
]
}
}
}
]
}
EDIT: These are the errors im getting:
jsonschemavalidator.net
Error parsing schema
Message: Error when resolving schema reference '#/allOf/1/properties/body/properties/foo'.
Path 'allOf[1].properties.body.properties.bar', line .., position ..
AJV:
can't resolve reference #/allOf/1/properties/body/properties/foo from id http://example.org/foo.schema.json"
Your schema is mostly right, although you've set an $id in a subschema.
The "$id" keyword defines a URI for the schema, and the base URI that
other URI references within the schema are resolved against.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-00#section-9.2
By adding an $id to a subschema, you've reset the base URI for other URI references, which includes any use of $ref within the subschema and its children.
$ref
...Resolved against the current URI base, it identifies the URI of a
schema to use.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-00#section-8
By changing your definition of bar to the following, your schema will be valid.
"bar": {
"$ref": "#/properties/foo"
}
Further edit as Relequestual requested in his later comment:
It is valid to have an absolute URI as subschema $id, but as noted it resets the base URI. The restrictions on $id values only apply when using it to create local URI fragment identifiers (if this does not mean anything to you, do not worry about it).
Referencing a property schema from another property schema directly is valid, but the more common best practice is to put such a schema under the "definitions" keyword and have both properties refer to that location. This is what I would recommend for maximum clarity:
{
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"allOf": [
{
"$schema": "http://json-schema.org/draft-06/schema#",
"$id": "http:/example.org/example.schema.json",
"type": "object",
"properties": {
"type": {
"type": "string"
},
"body": {
"type": "object"
}
},
"required": [
"type",
"body"
]
},
{
"properties": {
"body": {
"$schema": "http://json-schema.org/draft-06/schema#",
"$id": "http://example.org/foo.schema.json",
"type": "object",
"properties": {
"foo": {
"$ref": "#/definitions/whateverYouWantToCallIt"
},
"bar": {
"$ref": "#/definitions/whateverYouWantToCallIt"
}
},
"required": [
"foo",
"bar"
]
}
},
"definitions": {
"whateverYouWantToCallIt": {
"type": "number",
"minimum": 1
}
}
}
]
}

JSON Schema v4 "required" in nested object

I tried searching, but I'm not quite sure how to put this in words! The point of confusion is how "required" works in JSON schema v4 when there are nested key values with the same name.
For example, this schema:
{
"Root": {
"type": ["array", "null"],
"items": {
"type": "object",
"properties": {
"LevelOne": {
"required": ["id", "name", "LevelOneRepeat"],
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"LevelOneRepeat": {
"type": ["array", "null"],
"items": {
"type": "object",
"properties": {
"required": ["id", "name"],
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
}
}
}
}
}
}
Inside LevelOne, I have a required for "id", "name", and "LevelOneRepeat". However, inside LevelOneRepeat, I also have a required for "id" and "name".
Does required only check for elements in the same level, or also all child elements? Do I need to include the required inside LevelOneRepeat if the key values required (same name) are already listed in the level above?
I tested my JSON with my schema, but I might've messed up my code somewhere as no required are working anymore.
You have a couple of issues with your schema that is probably what has led to your confusion about how required works.
Here is the corrected schema.
{
"type": ["array", "null"],
"items": {
"type": "object",
"properties": {
"LevelOne": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"LevelOneRepeat": {
"type": ["array", "null"],
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" }
},
"required": ["id", "name"]
}
}
},
"required": ["id", "name", "LevelOneRepeat"],
}
}
}
}
The first problem is with the way you define nested objects. The value of each property must be a schema. See how I changed the LevelOne definition to see how to correctly define a nested object.
The second problem is that have the required keyword in the wrong place. It should be on the same level as the properties keyword, not nested within the properties object. This is why your required constraints weren't working. See how I changed the LevelOne and LevelOneRepeat definitions.
Once you fix these problems, hopefully it should be more clear that the required keyword only applies to the schema it is defined in. It does not apply to any parent or child schema.
The id in LevelOne and LevelOneRepeat are only coincidentally related. They have to be independently specified as required.