Jarede
Jarede

Reputation: 3498

Specifying an object should be empty if another object has properties in JSON schema

I have data that comes back from GraphQL, I'd like to verify that data with JSON schema before manipulating it.

There might be a better way of doing this in graphQL than I currently am, but the data that comes back can be of two types with the same properties:

e.g. a simplified version of the data

obj: {
  audio: {
    artists: []
  },
  video: {}
}

or

obj: {
  audio: {},
  video: {
    artists: []
  }
}

So validity would be:

I've built a simplified schema that looks like this:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "file://schemas/simple.schema.json",
  "title": "simplified data",
  "description": "simple",
  "type": "object",
  "properties": {
    "audio": {
      "type": "object"
    },
    "video": {
      "type": "object"
    }
  },
  "oneOf": [
    {
      "audio": {
        "type": "object",
        "properties": {
          "artists": {
            "type": "array"
          }
        }
      },
      "video": {
        "type": "object",
        "properties": {}
      }
    },
    {
      "audio": {
        "type": "object",
        "properties": {}
      },
      "video": {
        "type": "object",
        "properties": {
          "artists": {
            "type": "array"
          }
        }
      }
    }
  ]
}

but AJV doesn't seem to validate the data correctly when run against:

{
  "audio": {
    "artists": []
  },
  "video": {}
}

What might have I got wrong with my schema?

Upvotes: 1

Views: 1155

Answers (1)

Relequestual
Relequestual

Reputation: 12355

After an initial attempt, Jason pointed out a simpler solution...

Using oneOf, you can specify that only one of the objects may have at least one property.

You can test this here: https://jsonschema.dev/s/SSRaL

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "file://schemas/simple.schema.json",
  "properties": {
    "audio": {
      "type": [
        "object"
      ],
      "properties": {
        "artists": {
          "$comment": "whatever validation you want"
        }
      }
    },
    "video": {
      "type": [
        "object"
      ],
      "properties": {
        "artists": {
          "$comment": "whatever validation you want"
        }
      }
    }
  },
  "oneOf": [
    {
      "properties": {
        "video": {
          "minProperties": 1
        }
      }
    },
    {
      "properties": {
        "audio": {
          "minProperties": 1
        }
      }
    }
  ]
}

Upvotes: 3

Related Questions