Validation messages for deeply nested properties are masked by generic higher level messages
In situations where a schema has multiple level nested allOf, oneOf or anyOf properties, validation errors in the deeper nested properties do not get returned in the ValidationReport.
This validation information is present in the ProcessingMessage that gets returned from JsonSchema.validate. However, in SchemaValidator.validate the ProcessingMessage gets converted into a ValidationReport and only extracts the top-level and immediate sub-level message.
This leads to situations where, for example, a deeply nested enum validation might fail, and the message returned is something indecipherable like:
"message" : "[Path '/details'] Instance failed to match all required schemas (matched only 1 out of 2)",
"additionalInfo" : [ "/properties/details/allOf/0: Instance failed to match all required schemas (matched only 1 out of 2)" ],
See the attached zip file for an example unit test that demonstrates validating successfully against a shallow-nested schema (with enum validation message returned), and against a deeply nested schema (with enum validation message not returned).
As a solution, the ProcessingMessage json tree could be recursively walked down to its deepest nodes to extract all relevant messages, to populate the ValidationReport's sub-reports.
Alternatively, when creating the ValidationReport, the raw ProcessingMessage json could be attached to the report, so that developers could access that validation information and process that as they prefer (eg with json-path).
Comments (6)
-
Account Deactivated -
Hi Scott - thanks for raising this.
I think the best solution would be to walk the tree and add subreports. That was the original intention, but obviously I didn’t explore deep nesting enough
If you have a use case for accessing the JSON Schema
ProcessingMessage
I wouldn't have a strong objection to attaching that as aJsonNode
or something. I don't want to attach it as-is though, as that would be leaking the JSON Schema lib into the ValidationReport API, which would make it difficult to change implementations later. -
Account Deactivated James - I could change ValidationReport.Message field additionalInfo from a List<String> to a List<ValidationReport.Message> to encapsulate that nested structure. The only concern would be whether that broke compatibility for anyone who has made their own class implementation of ValidationReport.Message.
-
You could add a
List<ValidateReport.Message> nestedMessage
field or similar, but don't change theadditionalInfo
type. As you say, that would be an API breaking change. -
Account Deactivated @James Navin Sorry for the delay - I’ve implemented that change and created a pull request for you to review at PR #140
-
- changed status to resolved
Available in v2.5.0
- Log in to comment
@James Navin Do you have any thoughts on this? I’d be happy to implement this in a fork then raise a pull request, however I’d like to get your input on a preferred approach. Would it be better to include the original ProcessingMessage as a JsonNode in the ValidationMessage, or alternatively recursively walk the nested sub-reports to extract all relevant messages?
(Note: I am the issue author)