JSON Schema Validation Error in MarkLogic - XDMP-VALIDATEERRORS - json

Using MarkLogic version 10.0-4.2, I am trying to validate a simple JSON record against a simple JSON schema.
JSON Schema:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"SourceSystemName": {
"type": "string"
},
"BatchDtTm": {
"type": "string"
},
"SubjectArea": {
"type": "string"
},
"DocumentType": {
"type": "string"
},
"LastUpdatedDt": {
"type": "string"
},
"required": [
"SourceSystemName",
"BatchDtTm",
"SubjectArea",
"DocumentType",
"LastUpdatedDt",
]
}
}
Code being run in Query Console:
let jsonRecord = {"SourceSystemName":"ODH","BatchDtTm":"09/17/21 08:51:48:472723","SubjectArea":"Customer","DocumentType":"Preference","LastUpdatedDt":"09/17/21 03:59:53:629707"};
xdmp.jsonValidate(jsonRecord, cts.doc('/schemas/NewSchema.json').toString());
When I run the above code, I get error
XDMP-JSVALIDATEBADSCHEMA: Invalid schema "": ""
I'm not really sure what is 'invalid' about my schema. Can someone offer some insight into what MarkLogic is viewing as 'invalid'?

The second parameter for $schema is supposed to be the URI of the schema document.
$schema URI of the JSON schema to use for validation.
You are attempting to pass in the stringified content.
Try:
xdmp.jsonValidate(jsonRecord, '/schemas/NewSchema.json');
And ensure that the schema document is inserted into the Schemas database, not the content database.

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?

Can't validate a json with a schema using an external schema file

My issue
I need to validate a json file from a Json Schema.
I have a main schema and this schema should load an external schema file to validate some part of the json.
For different reasons I can't merge them. I do need 2 schema file.
I am using a $ref statement as proposed in this doc:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/test-json?view=powershell-7.2&WT.mc_id=DT-MVP-5004831
but whatever I try I have this error:
Cannot parse the JSON schema.
What I need
What is the right schema syntax to do this in my case.
Test case
I have this directories on my disk:
.
test.ps1
----/jsons
params.json
----/schemas
securities.json
storages.json
I run validation from this pretty simple PowerShell (test.ps1):
# read json param
$testFile = Get-Content "./jsons/params.json" -Encoding UTF8 | convertfrom-json -Depth 50
$testee = $testFile.parameters | convertto-json
# read json schema
$schemasFile = (Get-ChildItem -Path "./schemas/storages.json").FullName
# test json from schema
$result = $testee | Test-Json -SchemaFile $schemasFile
$result
My json (params.json):
{
"parameters": {
"storages": [
{
"comment": "Very important storage",
"name": "fdlmsto",
"securities": [
{
"comment": "Critical rule",
"kind": "MSI"
}
]
}
]
}
}
The main schema (storages.json):
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"required": [
"storages"
],
"properties": {
"storages": {
"$id": "#/properties/storages",
"type": "array",
"additionalProperties": false,
"items": [
{
"$id": "#/properties/storages/items",
"type": "object",
"additionalProperties": false,
"required": [
"name",
"comment"
],
"properties": {
"$ref": "#/schemas/securities.json",
"name": {
"type": "string",
"$id": "#/properties/storages/items/properties/name"
},
"comment": {
"type": "string",
"$id": "#/properties/storages/items/properties/comment"
}
}
}
]
}
}
}
and the child schema (securities.json):
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"additionalProperties": false,
"required": [
"securities"
],
"properties": {
"securities": {
"$id": "#/properties/securities",
"type": "array",
"additionalProperties": false,
"items": {
"$id": "/properties/securities/items",
"anyOf": [
{
"$id": "#/properties/securities/items/anyOf/0",
"type": "object",
"additionalItems": false,
"additionalProperties": false,
"required": [
"kind",
"comment"
],
"properties": {
"comment": {
"type": "string",
"$id": "#/properties/securities/items/anyOf/0/properties/comment"
},
"kind": {
"type": "string",
"$id": "#/properties/securities/items/anyOf/0/properties/kind"
}
}
}
]
}
}
}
}
What I tested
I tested several syntaxe for $ref:
#/schemas/securities.json
./schemas/securities.json
/schemas/securities.json
....
I also tried to set the schema in the repository of test.ps1
I checked that this is the securities section that don't work
Thank you
I edit the question to leave what worked for me:
Change storages.json like this:
"properties": {
"securities": {
"$ref": "securities1.json#/securities"
},
"name": {
"type": "string"
},
"comment": {
"type": "string"
}
}
Change securities.json as:
{
"securities": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"kind",
"comment"
],
"properties": {
"comment": {
"type": "string"
},
"kind": {
"type": "string"
}
}
}
}
}
And of course I applied all changed suggested in the post
It appears that the powershell cmdlet is powered by NJsonSchema, which at this stage doesn't support JSON Schema draft 2020-12.
There are several issues I see.
storages.json
"$schema": "https://json-schema.org/draft/2020-12/schema" declares this is a draft 2020-12 schema. As your schema doesn't use any 2020-12 features, I'd suggest using draft 7 as it'll definitely be supported by NJsonSchema.
Your schema is declaring itself to be the meta-schema with "$id": "https://json-schema.org/draft/2020-12/schema". The meta-schema is a special schema that validates other schemas. What you probably want here is just storages.json, or even better, a full URI like https://examp.le/schemas/storages.json. It's just an identifier though; it doesn't need to be downloadable.
Remove the internal $ids. They're only specifying relative location and not providing any more detail. This kind of thing is generally calculated at runtime.
Your $ref is wrong. #/schemas/securities.json is going to try to search for this location inside the current schema. You need a full URI here, and you'll want to declare that same URI as $id in securities.json as well. This may be what is producing the error.
At #/properties/storages, you have "type": "array" and "additionalProperties": false. Maybe you meant additionalItems? additionalProperties only works on objects. (I also see this in securities.json at #/properties/securities.)
Your use of items is an array. This will only validate the first item. I think you're wanting to validate all the items. If so, just use the schema as the value for items; don't wrap it in an array. (also seen in securities.json)
securities.json
This schema uses draft 4, which is quite old and a bit incompatible with later drafts. Specifically, I see it's using $id in several places, which replaced draft 4's id in draft 6. Since draft 4 doesn't recognize $id, it'll probably ignore them. Moreover, $ref-ing between drafts isn't something that's required (or perhaps even addressed) by the specification. (I added some tests to the test suite around this only about a week ago.) As with storages.json I'd suggest using draft 7 here.
As mentioned above, you'll want to add an $id to the root so that the $ref in storages.json can identify this schema properly.
As with storages.json, remove the interal $ids; they're not providing any additional function.
You use an anyOf but only declare a single schema. You don't need this. Just move the keywords in that subschema up to where the allOf is.
{
"type": "object",
"allOf": [ { ... } ]
}
// becomes
{
"type": "object",
...
}
Sorry this sounds like a pile-on. I realize you might be new with JSON Schema. The learning curve can be pretty steep.
Instead of the documentation provided by MS, I'd use Understanding JSON Schema for how to write schemas. Use the MS docs only for how to use the cmdlet.
Just to add one point to the excellent answer above: the array form of items is not valid in 2020-12 anyway - it was replaced with prefixItems.
But the advice to use draft-07 throughout is the right advice, as is the advice to use the schema form of items anyway.

JSON Schema Validation $ref outer documents

Im using org.everit.json.schema for json schema validation in a spring boot application.
I have the following schema, that references a json schema on the same directory. The directory is the resources directory.. and am using everit to load it.
When i do this i get the following exception
java.net.MalformedURLException: no protocol: dataset.json
it seems everit cannot find the other document.. how can i get the validator to pull in other documents..
example of what im doing..
main.json
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "test.json",
"title": "test",
"type": "object",
"description": "test.",
"properties": {
"data": {"$ref": "dataset.json"}
}
}
dataset.json
{
"type": "string",
"description": "The data ",
"enum": ["string", "integer"]
}
self referencing documents can be done by using ref: '[hash]'
also newtonSoft uses recursion well.'

Verifying JSON schema for uri and string together?

I am verifying below JSON schema for two separate JSON response which are same but only one difference is one returns 'system' as a string in format of uri and other returns plain string which cause failing of my second test case because for the second response it also look for a string in uri format.
How can i solve this issue in my schema?
{
"id": "/coding",
"type": "array",
"items": {
"type": "object",
"properties": {
"system": {
"type": "string"
"format": "uri"
}
}
}
}
You could just remove "format": "uri" from your schema.

how to extract the JSON schema (sub schema) of a property from complete object json schema

I need a help regarding schema extraction by property.
For example i have a JSON schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "A simple address format",
"type": "object",
"properties": {
"street-name": { "type": "string" },
"locality":{ "type": "string" },
"region": { "type": "string" },
"postal-code": { "type": "int" },
"country-name": { "type": "string"}
},
"required": ["locality", "region", "country-name"]
}
I have an use case, where i need to extract the schema corresponding to each property and send to another service, where it will do validation against the value and save in database. Here is the sample object i need to send to another service.
{
"propertyName": "street-name",
"value": "19, Canton street",
**"schema": { "type": "string" }**
}
The questions is,
how we extract the schema for a particular property from a give JSON schema??
Given the property path, Is there any nodejs module exists to do this schema extraction? or if there is any other solutions exists ?
Because this is very simple scenario, but if we have array, anyOf, OneOf type its getting complicated;
Thanks in advance ! Please let me know if the question is not clear !
sadish