0

I'm using Node 9.2.0 and ajv 6.0.0.

I have a schema that I wish to use negative lookbehind on, it's defined like:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "release format",
    "description": "A Release Format",
    "type": "object",
    "properties": {
        "id": {"type": "integer"},
        "title": {
            "anyOf": [
                {
                    "type": "string",
                    "pattern": "^((?!itunes).)*$"
                },
                {
                    "type": "string",
                    "pattern": "^((?!exclusive).)*$"
                },
                {
                    "type": "string",
                    "pattern": "^((?!ringtone).)*$"
                }
            ]
        }
    }
}

However, it appears that when I try and validate this with AJV using the following data: {"id": 123, "title": "world exclusive"} I don't get a validation error.

The code:

const Ajv = require('ajv');
class Validator {
  constructor() {
    this.releaseFormatSchema = JSON.parse(fs.readFileSync('./schemas/release-format.json'));
    this.schemaValidator = new Ajv({allErrors: true});
  }

  validate(data) {
    let validate = this.schemaValidator.compile(this.releaseFormatSchema);
    let valid = validate(data);
    console.log(valid);
    console.log(validate);
  }
}

where data would be: {"id": 123, "title": "world exclusive"}. I would expect this to error, however it's currently telling me that the data is valid.

Jarede
  • 3,310
  • 4
  • 44
  • 68
  • 1
    `(?!..)` is a negative lookahead, but I get your drift. It all can be combined with `^((?!a|b|c|d).)*$`, etc. which also matches the empty string. –  Jan 23 '18 at 17:59
  • `However, it appears that when I try and validate this with AJV using the following data: {"id": 123, "title": "world exclusive"} I don't get a validation error.` That's looks to be because it is matching one of the regex that doesn't have `exclusive` in it. Combining into a single regex will solve the problem –  Jan 23 '18 at 18:05
  • crap, doesn't help if i'm getting my terms confused... but if you have an answer where it would error on titles containing `exclusive`, `itunes` and `ringtone` please let me know. – Jarede Jan 23 '18 at 18:06
  • Yeah, try this _single_ regex: `^((?!itunes|exclusive|ringtone).)*$`, errors on an OR (not and) condition. –  Jan 23 '18 at 18:08
  • Or change `anyOf` to `allOf`. – SamWhan Jan 23 '18 at 18:09

1 Answers1

0

The answer was also found by @sln and @ClasG, anyOf does a union between titles patterns can match : "all except strings which contains itunes" union "all except strings which contains exclusive" union "...", which means all which not contains all the forbidden keywords. It can be fixed either

  • using allOf instead of anyOF

    "title": {
        "allOf": [
            {
                "type": "string",
                "pattern": "^((?!itunes).)*$"
            },
            {
                "type": "string",
                "pattern": "^((?!exclusive).)*$"
            },
            {
                "type": "string",
                "pattern": "^((?!ringtone).)*$"
            }
        ]
    }
    
  • using single type/pattern :

    "title": {
        "type": "string",
        "pattern": "^((?!itunes|exclusive|ringtone).)*$"
    }
    
Nahuel Fouilleul
  • 18,726
  • 2
  • 31
  • 36