ajv-cli icon indicating copy to clipboard operation
ajv-cli copied to clipboard

validation not working (invalid data accepted) when a schema is defined using shell process substitution/named pipes

Open DavidBiesack opened this issue 1 year ago • 1 comments

The bash shell has a feature called process substitution (details below) which allows creating named pipes. ajv (CLI) does not appear to work well with such named pipes

$ ajv validate -s <(longer pipeline that yield a JSON or YAML schema) <(longer pipeline that yield a JSON or YAML data file)
/dev/fd/62 valid

this shows the data is valid, even when it does not satisfy the schema.

Rewritten in a way that should be equivalent from a bash script yields different ajv results:

$ (longer pipeline that yield a JSON or YAML schema) > schema.json
$ (longer pipeline that yield a JSON or YAML data file) > data.json
$ ajv validate -s schema.json -d data.json
data.json invalid
[
  {
    instancePath: '/info/breakingChanges',
    schemaPath: '#/properties/info/properties/breakingChanges/const',
    keyword: 'const',
    params: { allowedValue: true },
    message: 'must be equal to constant'
  }
]

Here's a simpler use case

Save the attached files, which unfortunately GitHub required me to rename with .txt extensions, so rename with

$ mv schema.yaml.txt schema.yaml
$ mv data.yaml.txt data.yaml

)

Use the shell and js-yaml to convert the files from YAML to JSON:

$ npm i -g ajv-cli js-yaml  # Install if you don't already have these commands
$ ajv --spec=draft2020 validate -s <(js-yaml schema.yaml) -d <(js-yaml data.yaml)
/dev/fd/62 valid

Even though data.yaml is invalid (as per schema.yaml), this command incorrectly shows the file as valid.

(here, /dev/fd/62 is the named pipe for the pipeline js-yaml data.yaml )

Running ajv directly

$ ajv --spec=draft2020 validate -s schema.yaml -d data.yaml
data.yaml invalid
[
  {
    instancePath: '/info/breakingChanges',
    schemaPath: '#/properties/info/properties/breakingChanges/const',
    keyword: 'const',
    params: { allowedValue: true },
    message: 'must be equal to constant'
  }
]

In situations where longer pipelines are used to derive the schema (i.e. text pipelines on YAML or other content ) and a schema.yaml or schema.json file is not directly available, I think ajv should work with named pipes

ajv validate -s <(longer pipeline that yield a JSON or YAML schema) <(longer pipeline that yield a JSON or YAML data file)

without having to resort to temp files that one must then clean up/manage etc.


From the bash(1) man page:

Process Substitution

   Process substitution allows a process's input or output to be
   referred to using a filename.  It takes the form of <(list) or
   >(list).  The process list is run asynchronously, and its input
   or output appears as a filename.  This filename is passed as an
   argument to the current command as the result of the expansion.

DavidBiesack avatar Oct 16 '24 20:10 DavidBiesack

I came back here to check on the status of this.... and realized I forgot to upload the files. Doing so now.

schema.yaml.txt data.yaml.txt

As noted above, rename these as schema.yaml and data.yaml then try

ajv --spec=draft2020 validate -s <(js-yaml schema.yaml) -d <(js-yaml data.yaml)

while ajv can natively process yaml files, please consider other pipelines other than just js-yaml (for example, output of jq or many other command line tools)

DavidBiesack avatar May 27 '25 20:05 DavidBiesack