typescriptjsonschemaajv

JSON Schema propertyNames doesnt seem to work


i am trying to use a schema to validate some input data in an ionic WebApp. But it doesnt seem to work the way i want it to. Schema and example input data here: https://www.jsonschemavalidator.net/s/ukPB5SkA.

specifically the object should be allowed to contain properties "header" "footer" "color" and "typeface". Yet other properties seem to be allowed despite additionalProperties being set to false.

I also tired adding:

    "patternProperties": {
        ".*": "string"
    }

i use ajv in my project so i tried using a format:

import addFormats from 'ajv-formats';
import Ajv2019 from "ajv/dist/2019"
const ajv = new Ajv2019({strict: true, removeAdditional: 'all',  allowUnionTypes: true, passContext: true})
addFormats(ajv)
ajv.addFormat("collection", {
  type: "string",
  validate: (x) => Object.keys(Properties).includes(x)
})

enum Properties {
  'header',
  'footer',
  'color',
  'typeface'
}

const complexSchemaFormat = {
  "type": "object",
  "properties": {
    "propertyNames": {
      "type": "string",
      "format": "collection"
    },
    "additionalProperties": false
  }
} as const

    const complexInput2 = {
      "jiii": 2,
      "juuu": "laal"
    }
  protected doThing() {
    const complexIsValid3 = ajv.validate(complexSchemaFormat,complexInput2)
    console.log(complexIsValid3) // is true, should be false
    }

Solution

  • propertyNames is an applicator similar to properties. The description of this keyword states:

    The propertyNames keyword in is used to define constraints on the property names within an object instance. It allows you to specify a schema that all the property names in an object instance must adhere to.

    The way you have written your schema, the actual property name defined is propertyNames.

    {
      "propertyNames": "something"
    }
    

    It should be something like this where you want to constraint the naming to your enum. BUT, this doesn't give you way to constraint the values of those properties.

    {
    "$schema": "https://json-schema.org/draft/2019-09/schema",
    "propertyNames": {
       "pattern": "header|footer|color|typeface"
      }
    }
    

    You probably really want to do something like this where you don't even need to define a custom format. JSON Schema validation will validate what you are trying to do with the custom format with the following

    {
      "$schema": "https://json-schema.org/draft/2019-09/schema",
      "unevaluatedProperties": false,
      "patternProperties": {
        "header|footer|color|typeface": {
          "type": "string"
        }
      }
    }
    

    This basically says, any property defined in this schema must be one of the values in patternProperties and then it must validate as a string