Anbarasan Anbarasan - 1 month ago 13
JSON Question

jsonschema - dynamic properties with static properties

I have a schema to validate a json.

For certain properties i need them to have values of certain types.


  • If "attr" property is "a" then "val" property should be "integer"

  • If "attr" property is "x" then "val" property should be "boolean"

  • If "attr" property is "b" then "val" property should be "string" with
    format "ipv4"



and so on...

This, I can define with oneOff. For all other "attr" properties i need to them to be of a certain format, sort of like a catch all, with "val" property to be "string".


  • If "attr" matches pattern then "val" property should be "string".



can this be done.

This is the schema that i have at the moment.

{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"name": {
"title": "name",
"type": "string"
},
"attribute": {
"title": "attributes",
"type": "object",
"$ref": "#/definitions/expr",
}
},
"definitions": {
"expr": {
"properties": {
"attr": {
"title": "attribute"
},
"val": {
"title": "val"
}
},
"required": ["val", "attr"],
"oneOf": [
{
"properties": {
"attr": {"enum": ["a","b"]},
"val": {"type": "integer"}
}
},
{
"properties": {
"attr": {"enum": ["x"]},
"val": {"type": "boolean"}
}
},
{
"properties": {
"attr": {"pattern": "^[-A-Za-z0-9_]*$", "maxLength": 255},
"val": {"type": "string"}
}
}
]
}
},
"additionalProperties": false,
"required": [
"name",
"attribute"
]
}


The problem is the properties for which i am trying to restrict the value type, also match the catchall format. so when i am expecting an integer value, it is passing with string value.

For Example:

the below json will pass the schema, based on the first item of oneOff

{
"name": "shouldpass",
"attribute": {
"attr": "a",
"val": 1
}
}


the below json will pass, based on the last item of oneOff.

{
"name": "shouldpass2",
"attribute": {
"attr": "h",
"val": "asd"
}
}


the below json should fail, based on the first item of oneOff, but it is also passing, because it is matching the last item of oneOff.

{
"name": "shouldfail",
"attribute": {
"attr": "a",
"val": "string"
}
}


how to acheive this?

esp esp
Answer

You schema for attr in the last subschema could be:

{
    "pattern": "^[-A-Za-z0-9_]*$",
    "not": { "enum": ["a", "b", "x"] },
    "maxLength": 255
}

Alternatively, instead of "oneOf" you can use "switch" keyword from the next JSON-schema version proposals: http://epoberezkin.github.io/ajv/keywords.html#switch-v5-proposal

It's implemented in Ajv (I am the author).

Comments