david.emilsson
david.emilsson

Reputation: 2331

JSON Schema - array with multiple different object types

I'm writing a schema using draft/2020-12 to validate an array of multiple objects. I will be using YAML for the examples for readability (and it's YAML documents that are going to be validated).

I've seen many different approaches but none seem to do a very good job for some reason.

The data to validate

pipeline:
  - foo: abc
    someOption: 123
  - baz: def
    anotherOption: 223
  - foo: ghi

As you can see, the pipeline array contains objects that has completely different properties. The same object types can appear multiple times (there's 2 instances of an object containing foo, they are to be seen as the same object type).

Schema

$id: 'https://example.com/schema'
$schema: 'https://json-schema.org/draft/2020-12/schema'
type: object
properties: 
  pipeline:
    type: array
    additionalItems: false
    anyOf:
      - items:
          type: object
          additionalProperties: false
          properties:
            foo:
              type: string
            someOption: 
              type: integer
          required: [foo]
      - items:
          type: object
          additionalProperties: false
          properties:
            baz: 
              type: string
            anotherOption:
              type: integer
          required: [baz]

To me, this looks correct, although it fails validation and I can't quite see why...

Even if it had worked, I'm not sure if I'm supposed to use anyOf or oneOf in this case. Is it matching across all array items or per individual array item?

Upvotes: 4

Views: 7333

Answers (1)

Relequestual
Relequestual

Reputation: 12295

You have it slightly wrong. Currently your schema says... for the pipeline array, either, all of the items must be foo or all of the items must be baz.

You need to change your location of anyOf and items...

items applies to every item in the array. anyOf checks that any of the subschema values are valid against the instance location (in this case, each item in the array).

{
  "$id": "https://example.com/schema",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "pipeline": {
      "type": "array",
      "items": {
        "anyOf": [
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "foo": {
                "type": "string"
              },
              "someOption": {
                "type": "integer"
              }
            },
            "required": [
              "foo"
            ]
          }, {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "baz": {
                "type": "string"
              },
              "anotherOption": {
                "type": "integer"
              }
            },
            "required": [
              "baz"
            ]
          }
        ]
      }
    }
  }
}

Upvotes: 5

Related Questions