4
var schema = {
  "$schema": "http://json-schema.org/draft-07/schema",
  "$id": "http://example.com/example.json",
  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "$id": "#/properties/data",
      "type": "object",
      "required": [
        "id",
        "name",
        "description",
        "groups"
      ],
      "properties": {
        "id": {
          "$id": "#/properties/data/properties/id",
          "type": "integer"
        },
        "name": {
          "$id": "#/properties/data/properties/name",
          "type": "string"
        },
        "description": {
          "$id": "#/properties/data/properties/description",
          "type": "string"
        },
        "groups": {
          "$id": "#/properties/data/properties/groups",
          "type": "array",
          "items": {
            "$id": "#/properties/data/properties/groups/items",
            "anyOf": [
              {
                "$id": "#/properties/data/properties/groups/items/anyOf/0",
                "type": "object",
                "required": [
                  "id",
                  "name",
                  "description"
                ],
                "properties": {
                  "id": {
                    "$id": "#/properties/data/properties/groups/items/anyOf/0/properties/id",
                    "type": "integer"
                  },
                  "name": {
                    "$id": "#/properties/data/properties/groups/items/anyOf/0/properties/name",
                    "type": "string"
                  },
                  "description": {
                    "$id": "#/properties/data/properties/groups/items/anyOf/0/properties/description",
                    "type": "string"
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
};

And I have json result either:

{
    "data": {
        "id": 1,
        "name": "Contacts",
        "description": "Pre-installed contacts management for your account.",
        "groups": []
    }
}

or

{
    "data": {
        "id": 4,
        "name": "Update Container Sub Type 913",
        "description": "I'll calculate the virtual SQL bus, that should circuit the FTP sensor!",
        "groups": [
            {
                "id": 1,
                "name": "tech",
                "description": "tech description group"
            }
        ]
    }
}

And when I validate json schema, the second - valid, the first - invalid. How can I resolve it to do both as valid?

3
  • 2
    A little simplification, side from the answer: you don't need all those $ids. They just specify the locations, so they're implicit. Commented Mar 16, 2021 at 7:34
  • 3
    Your schema is fine. See jsonschema.dev/s/s3K9o. I suspect something is wrong with the validator you're using. Commented Mar 16, 2021 at 9:46
  • 1
    Whatever tool you used to generate this schema did a terrible job. I highly suggest you don't use it anymore. Also, I second that your schema is correct. The validator you are using has a bug. Commented Mar 16, 2021 at 17:24

2 Answers 2

3

As described in the JSON Schema Specification version 2020-12, it's possible to validate the minimum amount of items inside an array. Just use the property minItems.

You can write something like this:

{
    "$id": "#/properties/data/properties/groups",
    "type": "array",
    "minItems": 1,
    "items": {
       ...
    }
}
Sign up to request clarification or add additional context in comments.

Comments

2

edited: ** This does not answer the question **

Option 1 : Validators and Json-schema versions

edited: deleted wrong information.

Option 2 : discard the anyOf

The problem might be the anyOf: it means one or more of these , therefore, group cannot be empty. See the docs on json-schema.org for more info.

But why do you need an anyOf , when you only have one type of items ? Try :

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

  "type": "object",
  "required": [
    "data"
  ],
  "properties": {
    "data": {
      "$id": "#/properties/data",
      "type": "object",
      "required": [
        "id",
        "name",
        "description",
        "groups"
      ],
      "properties": {
        "id": {
          "$id": "#/properties/data/properties/id",
          "type": "integer"
        },
        "name": {
          "$id": "#/properties/data/properties/name",
          "type": "string"
        },
        "description": {
          "$id": "#/properties/data/properties/description",
          "type": "string"
        },
        "groups": {
          "$id": "#/properties/data/properties/groups",
          "type": "array",
          "items": {
                "$id": "#/properties/data/properties/groups/items/anyOf/0",
                "type": "object",
                "required": [
                  "id",
                  "name",
                  "description"
                ],
                "properties": {
                  "id": {
                    "$id": "#/properties/data/properties/groups/items/anyOf/0/properties/id",
                    "type": "integer"
                  },
                  "name": {
                    "$id": "#/properties/data/properties/groups/items/anyOf/0/properties/name",
                    "type": "string"
                  },
                  "description": {
                    "$id": "#/properties/data/properties/groups/items/anyOf/0/properties/description",
                    "type": "string"
                  }
                }
          }
        }
      }
    }
  }
}

So you can get rid of the anyOf constraints , and validate an empty array as it is allowed by default.

Option 3 : conditional schemas

If your validator doesn't accept an empty array of anyOfs (some does) , There might be a possibility to work something out with conditional structures like if, then ... see reference. something in the lines of :

  • if array size is > 0 then apply the "anyOf" sub-schema

Please let us know how you solved this issue.

4 Comments

No draft specifies that if a property is an array and is required that it needs to be non-empty. The issue you linked is about allowing the required keyword to be empty.
Also, while the reset of the answer isn't wrong, it is irrelevant because the schema is valid (other than the misuse of $ids). This is clearly a bug with the validator they are using.
Thanks @JasonDesrosier , I stand corrected. that explains a lot about most validators accepting empty arrays. May I ask, does it means that an array of anyOf can be empty too , despite the anyOf definition of 1+ ?
All the keywords that are defined to be an array of schemas, including anyOf, are defined to be non-empty.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.