Reputation: 3985
I'm trying to extend JSON schema, which defines an enum:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"objType": {
"enum": [ "A", "B" ]
},
"baseType": {
"type": "object",
"properties": {
"category": { "$ref": "#/definitions/objType" }
}
}
},
"properties": {
"A": {
"allOf": [
{ "$ref": "#/definitions/baseType" },
/* how to restrict inherited `category' to "A"? */
{ /* properties specific to A */ }
]
},
"B": {
"allOf": [
{ "$ref": "#/definitions/baseType" },
/* how to restrict inherited `category' to "B"? */
{ /* properties specific to B */ }
]
}
}
}
I'm not sure how restrict inherited enum property to specific value. For example:
// passes validation
{
"category": "A",
"prop_A": "blah A"
}
// fails because `prop_A' is not valid property for category "B"
{
"category": "B",
"prop_A": "blah A"
}
Thanks.
Upvotes: 0
Views: 2766
Reputation: 681
With Schema Draft v6 this seems to be possible:
{
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"oneOf": [
{
"additionalProperties": false,
"properties": {
"category": {
"type": "string",
"const": "A"
},
"prop_A": {
"type": "string"
}
}
},
{
"additionalProperties": false,
"properties": {
"category": {
"type": "string",
"const": "B"
},
"prop_B": {
"type": "string"
}
}
}
]
}
Upvotes: 0
Reputation: 693
JSON Schema is a constraint system rather than an object oriented system, so "inheritance" as a concept doesn't fit very well. See https://github.com/json-schema-org/json-schema-org.github.io/issues/148 for more information.
However, in your case, I think that the constraint system is exactly what you want. In a constraint system, you can always add more constraints, but you can never remove them. So restricting an enum to a subset of its "inherited" values is as simple as using "allOf"
to add a constraint of a single-valued enum over top of the original two-valued enum.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"objType": {
"enum": [ "A", "B" ]
},
"baseType": {
"type": "object",
"properties": {
"category": { "$ref": "#/definitions/objType" }
}
}
},
"properties": {
"A": {
"allOf": [
{ "$ref": "#/definitions/baseType" },
{ "objType": { "enum": [ "A" ] }.
{ /* properties specific to A */ }
]
},
"B": {
"allOf": [
{ "$ref": "#/definitions/baseType" },
{ "objType": { "enum": [ "B" ] }.
{ /* properties specific to B */ }
]
}
}
}
You just need to further constrain the enum for each type of property at the point where it is actually used.
Upvotes: 2
Reputation: 14715
In the Building a mount point schema example they do this a little differently. Each storage
refers to one of several types of objects:
"properties": {
"storage": {
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/diskDevice" },
{ "$ref": "#/definitions/diskUUID" },
{ "$ref": "#/definitions/nfs" },
{ "$ref": "#/definitions/tmpfs" }
]
},
and each of the object types includes a type
enum with a different value. e.g. diskDevice
specifies type
in this way
"properties": {
"type": { "enum": [ "disk" ] },
"device": {
"type": "string",
"pattern": "^/dev/[^/]+(/[^/]+)*$"
}
whereas nfs
specifies type
this way
"properties": {
"type": { "enum": [ "nfs" ] },
"remotePath": {
"type": "string",
"pattern": "^(/[^/]+)+$"
},
Perhaps you could consider refactoring your schema along those lines.
Upvotes: 0