How can we validate input property based on type property's enum value

70 views
Skip to first unread message

Abhishek Kekane

unread,
Dec 27, 2016, 4:05:30 AM12/27/16
to JSON Schema, abhishe...@nttdata.com, pooja....@nttdata.com
I want to validate input property based on other property. I am using oneOf in the schema. I have tried to use "dependencies" property but its not working. I am using draft-04 version. Following is my schema.

_TASK_SCHEMA = {
   
"type": {
       
"enum": [
           
"import", "export", "clone"
       
],
       
"type": "string"
   
},
   
"status": {
       
"enum": [
           
"pending",
           
"processing",
           
"success",
           
"failure"
       
],
       
"type": "string"
   
},
   
"input": {
       
"type": "object",
       
"oneOf": [
           
{"$ref": "#/definitions/import"},
           
{"$ref": "#/definitions/export"},
           
{"$ref": "#/definitions/clone"},
       
],
   
},
}

definitions
=  {
                 
"import": {
               
"additionalProperties": False,
               
"properties": {
                   
"import_from": {"type": "string"},
                   
"import_from_format": {"type": "string"},
                   
"image_properties": {"type": "object"}
               
}
           
},
           
"export": {
             
"additionalProperties": False,
               
"properties": {
                   
"export_from": {"type": "string"},
                   
"export_from_format": {"type": "string"},
                   
"export_properties": {"type": "object"}
               
}
           
},
           
"clone": {
               
"additionalProperties": False,
               
"properties": {
                   
"clone_from": {"type": "string"},
                   
"clone_from_format": {"type": "string"},
                   
"clone_properties": {"type": "object"}
               
}
           
}
     
}
raw = {
           
'name': "testing",
           
'properties':_TASK_SCHEMA,
           
'definitions': definitions,
           
'additionalProperties': False,
     
}

This is my input request body.

data = {
   
"type": "import",
   
"input": {
       
"import_from": "import from url",
       
"import_from_format": "import from format",
       
"image_properties": {}
   
}
}


jsonschema.validate(data, raw)

In the above schema, I am trying to validate "input" type parameter value which I defined in oneOf schema definition according to the "type" parameter value. But it’s not working.

For Example:
If type = "import" then, Input must have {"import_from" , "import_from_format" ,"image_properties"} properties.
If type = "export" then, Input must have {"export_from" , "export_from_format" , "export_properties"} properties.
If type = "clone" then, Input must have {"clone_from" , "clone_from_format" , "clone_properties"} properties.

NOTE:
I don't want to change the schema format (due to some project specific constraints)

Can anyone help me for the same?


Przemysław Wesołek

unread,
Dec 28, 2016, 5:56:07 AM12/28/16
to JSON Schema, abhishe...@nttdata.com, pooja....@nttdata.com
It greatly depends on the tools you are using. If going on a bleeding edge is not a problem for you, take a look at if-then-else feature https://github.com/json-schema-org/json-schema-spec/issues/180; have not used it myself, but looks like it is being added into ajv.

If you want to stay with draft-04, one way to handle this is to limit the enum's set of values in each of oneOf constraint. In your case it would be a bit complicated, however, as the "if part" (i.e. the enum) is one level above the "then part" (i.e. in a parent object). So you should "push" "input" filed into oneOf definition, something like this (not checked):

{
   
"name": "testing",
   
"properties": {

       
"type": {
           
"enum": [ "import", "export", "clone" ],
           
"type": "string"
       
},
       
"status": {
           
"enum": [ "pending", "processing", "success", "failure" ],
           
"type": "string"
       
},

       
"oneOf": [
           
{
               
"properties": {
                   
"type": { "enum": [ "import" ] },
                   
"input": { "$ref": "#/definitions/import" }
               
}
           
}, {
               
"properties": {
                   
"type": { "enum": [ "export" ] },
                   
"input": { "$ref": "#/definitions/export" }
               
}
           
}, {
               
"properties": {
                   
"type": { "enum": [ "clone" ] },
                   
"input": { "$ref": "#/definitions/clone" }
               
}
           
}]
       
}
   
},
   
"definitions": {
       
"import": {
           
"additionalProperties": false,

           
"properties": {
               
"import_from": {"type": "string"},
               
"import_from_format": {"type": "string"},
               
"image_properties": {"type": "object"}
           
}
       
},
       
"export": {

           
"additionalProperties": false,

           
"properties": {
               
"export_from": {"type": "string"},
               
"export_from_format": {"type": "string"},
               
"export_properties": {"type": "object"}
           
}
       
},
       
"clone": {

           
"additionalProperties": false,

           
"properties": {
               
"clone_from": {"type": "string"},
               
"clone_from_format": {"type": "string"},
               
"clone_properties": {"type": "object"}
           
}
       
}

   
},
   
"additionalProperties": false
}

Przemek

Henry H. Andrews

unread,
Dec 29, 2016, 1:53:19 AM12/29/16
to JSON Schema, abhishe...@nttdata.com, pooja....@nttdata.com
Minor correction:  you want the "oneOf" out at the same level as "properties" and "definitions.  The way you have it written in this answer is declaring a property called "oneOf" :-)  Everything directly under "properties" is a property name, you can't use schema keywords there.

Otherwise I agree with the solution.

cheers,
-henry

Przemysław Wesołek

unread,
Dec 29, 2016, 4:09:27 AM12/29/16
to JSON Schema, abhishe...@nttdata.com, pooja....@nttdata.com
Right, my mistake. :)

Przemek
Reply all
Reply to author
Forward
0 new messages