Search code examples
jsonenumsjsonschemaajvjsonpointer

Use object property keys as enum in JSON schema


I'm trying to validate a JSON file using JSON Schema, in order to find cases of "broken references". Essentially my file consists of items and groups, with each item belonging to a single group referenced by the groups property key, like so:

{
    "items": {
        "banana": {
            "name": "Banana",
            "group": "fruits"
        },
        "apple": {
            "name": "Apple",
            "group": "fruits"
        },
        "carrot": {
            "name": "Carrot",
            "group": "vegetables"
        },
        "potato": {
            "name": "Potato",
            "group": "vegetables"
        },
        "cheese": {
            "name": "Cheese",
            "group": "dairy"
        }
    },
    "groups": {
        "fruits": {
            "name": "Fruits"
        },
        "vegetables": {
            "name": "Vegetables"
        }
    }
}

In the example above the item cheese is to be considered invalid, as there are no dairy property in the groups object. I've tried to validate this using the following schema:

{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "title": "Food",
    "id": "food",
    "type": "object",
    "properties": {
        "items": {
            "type": "object",
            "patternProperties": {
                "^[A-Za-z0-9-_.:=]+$": {
                    "properties": {
                        "name": {
                            "type": "string",
                            "pattern": "^[A-Za-z- ]+$"
                        },
                        "group": {
                            "pattern": "^[a-z]+$",
                            "enum": {
                                "$data": "/groups"
                            }
                        }
                    }
                }
            }
        },
        "groups": {
            "type": "object",
            "patternProperties": {
                "^[A-Za-z0-9-_]+$": {
                    "properties": {
                        "name": {
                            "type": "string",
                            "pattern": "^[A-Za-z- ]+$"
                        }
                    }
                }
            }
        }
    },
    "additionalProperties": false
}

This has the effect that the enum for group is populated by the property values in groups, but what I want to do is use the property keys defined in groups.

If I add a property like e.g. groupIds and let that be an array of all property keys found in groups and specify the enum as "$data": "/groupIds" it does work, so I take this to be a JSON pointer issue.

The enum keyword in JSON Schema is defined as:

The value of this keyword MUST be an array. This array SHOULD have at least one element. Elements in the array SHOULD be unique.

So if I could only get JSON pointer to reference an object's keys rather than its values I guess the enum validation would just work. I'm thinking something like "$data": "/groups/.keys", "$data": "/groups/$keys" or similar, but haven't found it while googling or reading the spec. Is there such a thing or has it ever been proposed?


Solution

  • There is no such thing. It’s very close to general expressions inside JSON and it may have some use cases, but there is no such specification.