首页 > 解决方案 > Using multiple anyOf inside oneOf

问题描述

I wanted to create a schema where I will be having multiple objects inside "oneOf" which will be having many objects in anyOf format where some of the keys can be of required type(this part works) My schema :-

{
    "description": "schema v6",
    "type": "object",
    "oneOf": [
    {
    "properties": {
    "Speed": {
      "items": {
        "anyOf": [
          {
            "$ref": "#/definitions/speed"
          },
          {
            "$ref": "#/definitions/SituationType"
          }
        ]
      },
      "required": [
        "speed"
      ]
    }
  },
  "additionalProperties": false
        }
      ],
      "definitions": {
        "speed": {
          "description": "Speed",
          "type": "integer"
        },
        "SituationType": {
          "type": "string",
          "description": "Situation Type",
          "enum": [
            "Advice",
            "Depend"
              ]
            }
          }
        }

But when I'm trying to verify this schema but i'm able to authenticate some incorrect values like

    {
      "Speed": {
        "speed": "ABC",//required
        "SituationType1": "Advisory1" //optional but key needs to be correct
      }
    }

correct response which i was expecting was

    {
      "Speed": {
        "speed": "1",
        "SituationType": "Advise" 
      }
    }

标签: jsonschemajsonschema

解决方案


First, you need to set the schema type correctly, otherwise implmentations may assume you're using the latest JSON Schema version (currently draft-7).

So, in your schema root, you need the following:

"$schema": "http://json-schema.org/draft-06/schema#",

Second, items is only applicable if the target is an array. Currently your schema only checks the following:

If the root object has a property of "Speed", it must have a key of "speed". The root object must not have any other properties.

And nothing else.

Your use of definitions and how you reference them is probably not what you intended.

It looks like you want Speed to contain speed which must be an integer, and optionaly SituationType which must be a string, limited by enum, and nothing else.

Here's the schema I have based on that, which passes and fails correctly based on your given example data:

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "type": "object",
  "oneOf": [
    {
      "properties": {
        "Speed": {
          "properties":{
            "speed": {
              "$ref": "#/definitions/speed"
            },
            "SituationType": {
              "$ref": "#/definitions/SituationType"
            }
          },
          "required": [
            "speed"
          ],
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    }
  ],
  "definitions": {
    "speed": {
      "description": "Speed",
      "type": "integer"
    },
    "SituationType": {
      "type": "string",
      "description": "Situation Type",
      "enum": [
        "Advice",
        "Depend"
      ]
    }
  }
}

You need to define the properties for Speed, because otherwise you can't prevent additional properties, as additionalProperties is only effected by adjacent an properties key. We are looking to created a new keyword in draft-8 to support this kind of behaviour, but it doesn't look like you need it in your example (Huge Github issue in relation).

Adding additionalProperties false to the Speed schema now prevents other keys in that object.

I SUSPECT that given your question title, there may be more schema at play here, and you've simplified it for this question. If you have a more detailed schema with more complex issues, I'd be happy to help also.


推荐阅读