I am trying to validate a json file with nested references where the children references are in a sub-folder of the parent one. The files are organised as following:
root/schemas/user
root/schemas/sub-schemas/address
root/schemas/sub-schemas/city
and they are referenced user -> sub-schemas/address -> sub-schemas/city
I am doing this in R with the package {jsonvalidate} but I guess my question is more about the way references work in the json-schema, rather than R specific. Here's the reproducible code in R which gives the error:
library(jsonvalidate)
library(testthat)
json_to_validate = '
{
"address":{
"city":"Firenze"
}
}
'
root = file.path(tempdir(), "jsonvalidate")
dir = "schemas"
subdir = "sub-schemas"
dir.create(file.path(root, dir, subdir), recursive = TRUE, showWarnings = FALSE)
user_file = "user"
user_schema_path = file.path(root, dir, user_file)
address_file = "address"
address_rel_path = file.path(subdir, address_file)
city_file = "city"
city_rel_path = file.path(subdir, city_file)
user_schema_ref = sprintf('
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "file://%s",
"type":"object",
"required":["address"],
"properties":{
"address":{
"$ref": "%s"
}
}
}
', user_schema_path, address_rel_path)
address_schema = sprintf('
{
"$schema": "http://json-schema.org/draft-07/schema",
"type":"object",
"properties":{
"city":{
"$ref": "%s"
}
}
}
', city_rel_path)
city_schema = sprintf('
{
"$schema": "http://json-schema.org/draft-07/schema",
"type":"string",
"enum":["Firenze"]
}
')
write(user_schema_ref, user_schema_path)
write(address_schema, file.path(root, dir, address_rel_path))
write(city_schema, file.path(root, dir, city_rel_path))
list.files(root, recursive = TRUE)
#> [1] "schemas/sub-schemas/address" "schemas/sub-schemas/city"
#> [3] "schemas/user"
cat(user_schema_ref)
#>
#> {
#> "$schema": "http://json-schema.org/draft-07/schema",
#> "$id": "file:///var/folders/yq/82fd9hrj1zs7kx2hqbqlg9280000gp/T//Rtmpguupsl/jsonvalidate/schemas/user",
#> "type":"object",
#> "required":["address"],
#> "properties":{
#> "address":{
#> "$ref": "sub-schemas/address"
#> }
#> }
#> }
cat(address_schema)
#>
#> {
#> "$schema": "http://json-schema.org/draft-07/schema",
#> "type":"object",
#> "properties":{
#> "city":{
#> "$ref": "sub-schemas/city"
#> }
#> }
#> }
cat(city_schema)
#>
#> {
#> "$schema": "http://json-schema.org/draft-07/schema",
#> "type":"string",
#> "enum":["Firenze"]
#> }
json_validate(entry1, user_schema_path, engine = "ajv",
verbose = TRUE, greedy = TRUE,
error = FALSE)
#> Error in context_eval(join(src), private$context, serialize, await): Error: can't resolve reference sub-schemas/city from id sub-schemas/address
Created on 2022-08-24 with reprex v2.0.2
I managed to make it work if I put the files all in the same folder:
root/schemas/user
root/schemas/address
root/schemas/city
And I reference as following:
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "file:///var/folders/yq/82fd9hrj1zs7kx2hqbqlg9280000gp/T//Rtmpguupsl/jsonvalidate/schemas/user",
"type":"object",
"required":["address"],
"properties":{
"address":{
"$ref": "address"
}
}
}
{
"$schema": "http://json-schema.org/draft-07/schema",
"type":"object",
"properties":{
"city":{
"$ref": "city"
}
}
}
But, as soon as I move the sub-schemas in a sub-folder I can't make it work.
It appears that the issue was specific to the R package jsonvalidate
and the issue has been resolved in PR #62. The reference child2
in the example below is resolved against child1
so it should not contain the sub folder.
library(jsonvalidate)
parent = c(
'{',
' "type":"object",',
' "required":["child1"],',
' "properties":{',
' "child1":{',
' "$ref":"sub/child1.json"',
' }',
' }',
'}'
)
child1 = c(
'{',
' "type":"object",',
' "properties":{',
' "child2":{',
' "$ref":"child2.json"',
' }',
' }',
'}'
)
child2 = c(
'{',
' "type":"string",',
' "enum":["test"]',
'}'
)
dir = file.path(tempdir(), "jsonvalidate_test")
schemadir = file.path(dir, "schemas")
schemasubdir1 = file.path(schemadir, "sub")
schemasubdir2 = file.path(schemasubdir1)
dir.create(schemasubdir2, recursive = TRUE, showWarnings = FALSE)
writeLines(parent, file.path(schemadir, "parent.json"))
writeLines(child1, file.path(schemasubdir1, "child1.json"))
writeLines(child2, file.path(schemasubdir2, "child2.json"))
list.files(schemadir, recursive = TRUE)
#> [1] "parent.json" "sub/child1.json" "sub/child2.json"
json_validate('{"child1":{"child2":"test"}}', file.path(schemadir, "parent.json"), engine = "ajv")
#> [1] TRUE
json_validate('{"child1":{"child2":""}}', file.path(schemadir, "parent.json"), engine = "ajv")
#> [1] FALSE
unlink(dir, recursive = TRUE)
Created on 2022-09-21 with reprex v2.0.2