I'm trying to validate a required property with if statement in JsonSchema, but it isn't informing me the property's error in detail.
The validation has been made correctly, but the error don't specify the property and which validation failed.
It works for required properties in the root level of an object, but when I specify a required property inside an object, it just warn that the json doesn't match and specify the then
or else
schema's path.
Schema example:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"name",
"partners"
],
"properties": {
"partners": {
"type": "array",
"items": {
"type": "object",
"if": {
"properties": {
"juridical": {
"type": "object"
},
"natural": {
"type": "null"
}
}
},
"then": {
"properties": {
"juridical": {
"required": [ "tradeName" ],
"properties": {
"tradeName": {
"type": "string"
}
}
}
}
},
"else": {
"properties": {
"natural": {
"required": ["name"],
"properties": {
"name": {
"type": "string"
}
}
}
}
}
}
}
}
}
Json example:
{
"name": "Joao",
"partners": [
{
"juridical": null,
"natural": {
}
},
{
"juridical": {
"tradeName": ""
},
"natural": null
}
]
}
It should warns that the first partner have the "name" required (Required properties are missing from object: name.
), instead it only tell me: JSON does not match schema from 'else'.
.
With a simple schema like this it works as expected:
Schema example:
{
"if": { "properties": { "power": { "minimum": 9000 } } },
"then": { "required": [ "disbelief" ] },
"else": { "required": [ "confidence" ] }
}
Json example:
{ "power": 10000 }
I'm using JsonSchemaValidator.net to verify the results.
Basically, JSON document either validates against JSON schema or not. This logic goes down through all sub-schemas and conditionals.
The content of error messages depends on specific implementation of JSON Schema validator. The one you use comes from a specific provider. As pointed by Relequestal, you cannot expect specific type of error message handling from specific implementation, unless it's what the provider documentation describes.
How about filing a suggestion to authors of the validator you use about extending messages for if-then-else case, feeding in your case?
Alternative approach: As I understand, your goal is to get as much specific error information as possible with this specific validator. It is what it is, so an alternative schema might fit the goal. As JSON Schema itself is a JSON document, thus you may consider a workaround by naming nodes in Schema in some consistent manner and using one of logical operators ("anyOf" (logical OR), "allOf" (logical AND), "oneOf" (logical XOR) ) instead of if-then-else.
Please note: schema based validator, in case of "allOf", "anyOf", "oneOf" is expected to run through all schemas until the logical condition is satisfied.
"allOf" - will check always if JSON doc validates against all schemas
(AND)
"anyOf" - will check if JSON doc validates at least against 1 schema
(OR, so some validator implementations might stop checking after
first positive result as it's sufficient to evaluate check against
"anyOf" to true),
"oneOf" - will check always if JSON doc validates exactly against
one of enlisted schemas by checking against all of them (XOR)
(see: https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.6.7.1 )
Thus if validated instance doesn't match schemas in above cases, the validator implementation may produce some 'false positives' in terms of error messages, as it will enlist issues encountered vs all schemas. It simply can't read our minds and guess what we meant by providing specific JSON doc, so it throws all on us to judge and decide.
One of many solutions could be to define variants of "juridical" and "natural" and combine them logically into schemas as in your case it seems you expect:
either juridical is an object (+relevant constraints) AND natural is not an object or juridical is not an object and natural is an object
(+relevant constraints).
Alternative schema (please note the "examples" section containing some test JSON documents):
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"name",
"partners"
],
"properties": {
"partners": {
"type": "array",
"items": {
"type": "object",
"anyOf" : [
{"$ref" : "#/definitions/juridical-is-object-and-natural-is-null"},
{"$ref" : "#/definitions/juridical-is-not-an-object-and-natural-is-an-object"}
],
"required" : ["natural","juridical"]
}
}
},
"examples" : [
{
"name": "Joao",
"partners": [
{
"juridical": null,
"natural": {
}
},
{
"juridical": {
"tradeName": ""
},
"natural": null
}
]
},
{
"name": "Joao",
"partners": [
{
"juridical": null,
"natural": {
"name" : ""
}
},
{
"juridical": {
"tradeName": ""
},
"natural": null
}
]
},
{
"name": "Joao",
"partners": [
{
"juridical": null,
"natural": {
}
},
{
"juridical": {
"tradeName": ""
},
"natural": null
},
{
"juridical" : [],
"natural" : {}
}
]
}
],
"definitions" : {
"natural" : {
"is-object" : {
"type" : "object",
"required": ["name"],
"properties": {
"name": {
"type": "string"
}
}
},
"is-not-an-object" : {
"not" : { "type" : "object" }
},
},
"juridical" : {
"is-object" : {
"type" : "object",
"required": ["tradeName"],
"properties": {
"name": {
"type": "string"
}
}
},
"is-not-an-object" : {
"not" : { "type" : "object" }
},
},
"juridical-is-object-and-natural-is-null" : {
"properties" : {
"natural" : {"$ref" : "#/definitions/natural/is-not-an-object"},
"juridical" : {"$ref" : "#/definitions/juridical/is-object"}
},
},
"juridical-is-not-an-object-and-natural-is-an-object" : {
"properties" : {
"natural" : {"$ref" : "#/definitions/natural/is-object"},
"juridical" : {"$ref" : "#/definitions/juridical/is-not-an-object"}
}
},
}
}
Notes:
"not" : { schema } error message might be confusing for casual users, but it conforms to the spec: https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.6.7.4
Update
As explained in comments, you are after error details. Given the constraints of the selected tool in terms of if-then-else error details for more complex schemas, did you try to reshape schema using different keywords to trigger as less overhead messages as possible?
Alternative schema 2
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"name",
"partners"
],
"properties": {
"partners": {
"type": "array",
"items" : {
"properties" : {
"natural" : {
"if" : { "type" : "object" },
"then" : { "required" : ["name"] },
"dependencies" : {
"name" : {
"properties" : {
"name" : {"type" : "string"}
}
}
}
},
"juridical" : {
"if" : { "type" : "object" },
"then" : { "required" : ["tradeName"] },
"dependencies" : {
"tradeName" : {
"propertyNames" : {
"enum" : ["tradeName"]
},
"properties" : {
"tradeName" : {"type" : "string"}
}
}
}
}
},
"anyOf" : [
{"$ref" : "#/definitions/natural-is-null-juridical-is-an-object"},
{"$ref" : "#/definitions/natural-is-an-object-juridical-is-null"}
]
}
}
},
"definitions" : {
"natural-is-null-juridical-is-an-object" : {
"properties" : {
"natural" : { "type": "null"},
"juridical" : { "type" : "object"}
}
},
"natural-is-an-object-juridical-is-null" : {
"properties" : {
"natural" : { "type": "object"},
"juridical" : { "type" : "null"}
}
},
},
"examples" : [
{
"name": "Joao",
"partners": [
{
"juridical": null,
"natural": {
}
},
{
"juridical": {
"tradeName": "",
},
"natural": null
},
{
"juridical" : {},
"natural" : {}
},
{
"juridical" : null,
"natural" : null
}
]
},
]
}