A json Schema with an array of a $ref or an enum - jsonschema

I would like to have a Json Schema that would enforce an array of $ref and an enum of null. I have accidentally defined a tuple - not what I want. Here is my current schema (note I must use draft-04):
{
"$schema": "http://json-schema.org/draft-04/schema#",
"version": "4.4.0",
"title": "myCollection",
"description": "Resume/CV",
"type": "object",
"properties": {
"EmploymentHistories": {
"type": "array",
"items": {
"oneOf": [
{
"$ref": "../../../Common/json/base/TextType.json#"
},
{
"enum": [
null
]
}
]
},
"additionalProperties": false
}
}
}
And here is an instance I would like:
{
"EmploymentHistories": [
{
"value": "String",
"languageCode": "aa"
},
{
"value": "String",
"languageCode": "aa"
},
null,
null
]
}
But I am getting an error on validation like:
File D:\Dev\Proj\Recruiting\json\resumecv\samples\Untitled5.json is not valid.
A value of type 'null' is not permitted here.
Reason: it must be of one of the following types (see below)
'string'
'object'
Hint: Either 'type' is present and doesn't contain 'null' or 'enum' is present and doesn't contain a value of type 'null'.
Error location: EmploymentHistories / 3
Details
Array item '2' is not valid.
Property 'EmploymentHistories' is not valid.
A value of type 'null' is not permitted here.
Reason: it must be of one of the following types (see below)
'string'
'object'
Hint: Either 'type' is present and doesn't contain 'null' or 'enum' is present and doesn't contain a value of type 'null'.
Error location: EmploymentHistories / 4
Details
Array item '3' is not valid.
Property 'EmploymentHistories' is not valid.
Any help is appreciated.n

This looks like a bug in the validator implementation you are using. It seems to be saying that "enum": [null] is not allowed in a schema. The error is incorrect. This should be perfectly fine. However, you can probably work around this bug by changing it to "type": "null", which should have the same effect.

Related

In JSON schema, define and reference a reusable enum type?

I noticed the following: Reusable enum types in json schema , which talks about defining a reusable enum type in JSON schema.
I would have assumed USING this reusable enum type would be trivial, simply specifying (in this case) the value of "MyEnum" for a "type" value.
I don't know if the results from Oxygen XML are authoritative, but I tried something like the following:
{
"$schema": "https://json-schema.org/draft/2019-09/schema#",
"type": "object",
"properties": {
"content": {"$ref": "#/definitions/content_type"}
},
"additionalProperties": false,
"definitions": {
"costCategory_type": {
"type": "object",
"enum": ["VH", "H", "M", "L"]
},
"allowedDevices_type": {
"type": "object",
"properties": {
"costCategory": {
"type": "costCategory_type"
},
On the line near the bottom of this, where I reference "costCategory_type", Oxygen gives me a syntax error, saying
#/definitions/allowedDevices_type/properties/costCategory/type: unknown type: [costCategory_type]
What am I missing?
Yes, the type keyword can only have values from the list null, boolean, object, array, string, number, integer. You can reference definitions with the $ref keyword:
...
"properties": {
"costCategory": {
"$ref": "#/definitions/costCategory_type",
}
}
(incidentally, your definition won't ever evaluate successfully as-is since you define it as being the "object" type, but the list of values in the enum are all strings.)

Using a $ref and other properties within a JSON Schema

In a JSON Schema is is valid to have a $ref and then other properties within the same schema, for example.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"title": "My schema",
"properties": {
"scripts": {
"$ref": "#/definitions/scriptsBase",
"description": "More docs.",
"minLength": 10
}
},
"definitions": {
"scriptsBase": {
"type": "string",
"description": "Base Description",
"minLength": 5
}
}
}
If this is allowable, then what are the rules when it comes to resolving properties defined in the $refed and the $refing schemas (in this example minLength and description. But potentially this could become much more complex if allOf etc where defined in both.
Found the answer in json schema property description and "$ref" usage, basically if a $ref exists all other properties are ignored.
https://datatracker.ietf.org/doc/html/draft-pbryan-zyp-json-ref-03#section-3
Syntax
A JSON Reference is a JSON object, which contains a member named
"$ref", which has a JSON string value. Example:
{ "$ref": "http://example.com/example.json#/foo/bar" }
If a JSON value does not have these characteristics, then it SHOULD
NOT be interpreted as a JSON Reference.
The "$ref" string value contains a URI [RFC3986], which identifies
the location of the JSON value being referenced. It is an error
condition if the string value does not conform to URI syntax rules.
Any members other than "$ref" in a JSON Reference object SHALL be
ignored.

AnyOf vs type array

Are there any differences between the following two JSON schemas validations or do they validate the same data structure?
SomeProperty
{
"type": ["integer","string"]
}
SomeProperty
{
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
]
}
They are equivalent!
type
The value of this keyword MUST be either a string or an array. If it
is an array, elements of the array MUST be strings and MUST be unique.
String values MUST be one of the six primitive types ("null",
"boolean", "object", "array", "number", or "string"), or "integer"
which matches any number with a zero fractional part.
An instance validates if and only if the instance is in any of the
sets listed for this keyword.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.1.1
Notice the last section "...in any of..."

Is there a way to set property value format requirements based on a condition of the property name?

I have a simple JSON schema:
{
"properties": {
"name": {
"type": "string"
}
},
"type": "object"
}
It requires that name property is a string. This schema does not restrict additional properties, e.g.
{
name: 'foo',
url: 'http://foo'/
}
The latter is a valid input.
Is there a way to set a property value format requirement based on a conditional property name match?, e.g. any property that contains url string in it must correspond to the following schema:
{
"type": "string",
"format": "url"
}
Therefore, an input:
{
name: 'foo',
location_url: 'not-a-valid-url'
}
would cause an error because location_url does not contain a valid URL?
I'd imagine, a schema for something like this would look like:
{
"properties": {
"name": {
"type": "string"
}
},
"matchProperties": {
"/url/i": {
"type": "string",
"format": "url"
}
}
"type": "object"
}
where matchProperties is a keyword I made up.

reusing an object for multiple JSON schemas

I have two separate JSON schemas (used to validate HTTP request endpoints for a REST API) where they both accept the same exact object, but have different required fields (this is a create vs update request). Is there a way I can reuse a single definition of this object and only change the required fields? I know how to use $ref for reusing an object as a property of another object, but I cannot figure out how to reuse an entire object as the top-level object in a schema. My failed attempt so far:
event.json
{
"id": "event",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"start_date": {
"type": "integer"
},
"end_date": {
"type": "integer"
},
"description": {
"type": "string"
}
},
"additionalProperties": false
}
event-create.json
{
"id": "event-create",
"type": "object",
"$ref": "event",
"additionalProperties": false,
"required": [ "name", "description" ]
}
Obviously that doesn't work. It seems like it tries to insert the entirety of 'event' into the definition of 'event-create', including the ID and such. I tried referincing event#/properties to no avail. I can't seem to do a $ref as the sole value inside a properties property either. Any ideas?
Any members other than "$ref" in a JSON Reference object SHALL be ignored.
- https://datatracker.ietf.org/doc/html/draft-pbryan-zyp-json-ref-03#section-3
This is why your example doesn't work. Anything other than the $ref field is supposed to be ignored.
Support for $ref is limited to fields whose type is a JSON Schema. That is why trying to use it for properties doesn't work. properties is a plain object whose values are JSON Schemas.
The best way to do this is with allOf. In this case allOf can sort-of be thought of as a list of mixin schemas.
{
"id": "event-create",
"type": "object",
"allOf": [{ "$ref": "event" }],
"required": ["name", "description"]
}
I found some syntax that seems to work, but I'm not terribly happy with it:
{
"id": "event-create",
"allOf": [
{ "$ref": "event" },
{ "required": [ "name", "description" ] }
]
}
Seems like an abuse of the allOf operator, particularly for another case where there are no required fields (thus only one element insid the allof). But it works, so I'm going with it unless someone has a better idea.