10

I'm trying to validate a string(Phone number) with this regex ^+[0-9]{9,12}$

but I get this error ... .pattern should match format "regex" ...

I've been through the documentation at https://ajv.js.org etc. looked at examples etc. and tried a lot of variations, but can't seem to figure out what is wrong with my code.

Here is my code:

const schema = {
    type: 'object',
    properties: {
        users: {
            type: 'array',
            items: {
                type: 'object',
                properties: {
                    userReference: { type: 'string' },
                    phone: {
                        type: 'string'
                        , pattern: "^\+[0-9]{9,12}$" // If I remove this line, the model is seen as valid (and no errors)
                    }
                }
            }
        }
    },
    required: ['users'],
    errorMessage: { _: "One or more of the fields in the 'legacy' data path are incorrect." }
};

const schemaSample = {
    "users": [
        {
            "phone": "+25512345678", // should be valid
            "userReference": "AAA"
        },
        {
            "phone": "+5255 abc 12345678", // should be invalid
            "userReference": "BBB"
        }
    ]
};

var ajv = Ajv();
ajv.addSchema(schema, 'schema');

var valid = ajv.validate('schema', schemaSample);
if (valid) {
    console.log('Model is valid!');
} else {
    console.log('Model is invalid!');
}

Link to JSFiddle: http://jsfiddle.net/xnw2b9zL/4/ (Open Console / Debugger to see the full error)

customcommander
  • 17,580
  • 5
  • 58
  • 84
LegionDev
  • 1,391
  • 4
  • 15
  • 29
  • 3
    You most probably forgot to double escape: `"\+"` should be `"\\+"` – customcommander Jun 05 '20 at 15:47
  • 1
    I've literally spent HOURS on this damn thing!! Thanks that did the trick. If you post that as the answer I'll mark it as correct else I'll answer my own question later. – LegionDev Jun 05 '20 at 15:52

3 Answers3

10

TL; DR

Your regular expression is valid in a literal notation form but not in a constructor form where it is embedded into a string.

"\+""\\+"

When embedding a regular expression into a string, double check your escape characters!

Why?

Because useless escape characters will be ignored. If it wasn't for constructing a regular expression you have no reason to escape a '+' character:

"\+" === "+"
//=> true

The error you saw had nothing to do with the data, it was in the construction of the schema. As you can see here:

const ajv = new Ajv;

try {
  ajv.compile({type: 'string' , pattern: '^\+[0-9]{9,12}$'});
} catch (e) {
  console.log(`ERR! ${e.message}`);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/6.12.2/ajv.min.js"></script>

But digging deeper, it has nothing to do with Ajv either. Ajv does mention:

Ajv uses new RegExp(value) to create the regular expression that will be used to test data.

See https://ajv.js.org/keywords.html#pattern

So what does it mean to do new RegExp("\+")? Let's find out:

// similar error because "\+" and "+" are the same string
try { new RegExp("\+") } catch (e) { console.log(e.message) }
try { new RegExp("+") } catch (e) { console.log(e.message) }

Related

customcommander
  • 17,580
  • 5
  • 58
  • 84
  • One simple trick you can use is RegExp's toString `/(^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$)/.toString().slice(1,-1)` will automatically escape it for you. Slice allows use directly because the '/' are interpreted literally – Ray Foss Apr 26 '22 at 15:56
2

Your regex is wrongly stringified. To avoid mistakes you can use native Regex as follow:

{
  type: 'string', 
  pattern: /^\+[0-9]{9,12}$/.toString()
}
Eydwales
  • 251
  • 4
  • 9
1

In addition to @customcommander comment.

The documentation about format state that :

regex: tests whether a string is a valid regular expression by passing it to RegExp constructor.


In javascript when you declare a string the backslashes will be interpreted. That's why you need to double the backslashes.

If you don't, what you are passing to Avg and in fine to new RegExp(...) is the string "^+[0-9]{9,12}$", which is an incorrect RegExp.

enter image description here


PS: nice dog

Orelsanpls
  • 22,456
  • 6
  • 42
  • 69
  • 1
    I thought my regex was formatted correctly, as I entered it into regex101 and generated javascript for it, and it generated /^\+[0-9]{9,12}$/gm, but I now see it's not generated in a string. So never thought to double check my regex. – LegionDev Jun 05 '20 at 16:00