tdegrunt / jsonschema

JSON Schema validation
Other
1.82k stars 262 forks source link

pattern does not work when use a regexp with attributes #387

Open yhojann-cl opened 1 year ago

yhojann-cl commented 1 year ago

By example:

const jsonschema = require('jsonschema');

const results = (new jsonschema.Validator()).validate(
  { uuid: 'f9d15cc5-1a53-4733-9ae7-f1675c8428a7' }, // Object to validate
  { // Schema
    type: 'object',
    properties: {
      uuid: {
        type: 'string',
        pattern: /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
      }
    },
    required: [ 'uuid' ]
  },
  { required: true, allowUnknownAttributes: false }); // Settings

console.log(results.errors);

Says:

[
    ValidationError {
      path: [Array],
      property: 'instance.uuid',
      message: 'does not match pattern "/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i"',
      schema: [Object],
      instance: 'f9d15cc5-1a53-4733-9ae7-f1675c8428a7',
      name: 'pattern',
      argument: /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
      stack: 'instance.uuid does not match pattern "/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i"'
    }
  ]

But the expression and value are valid:

$ node
Welcome to Node.js v18.16.1.
Type ".help" for more information.
> 'f9d15cc5-1a53-4733-9ae7-f1675c8428a7'.match(/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i)
[
  'f9d15cc5-1a53-4733-9ae7-f1675c8428a7',
  index: 0,
  input: 'f9d15cc5-1a53-4733-9ae7-f1675c8428a7',
  groups: undefined
]
yhojann-cl commented 1 year ago

I found the problem in lib/attribute.js:687:

/**
 * Validates whether the instance value matches the regular expression, when the instance value is a string.
 * @param instance
 * @param schema
 * @return {String|null}
 */
validators.pattern = function validatePattern (instance, schema, options, ctx) {
  if (!this.types.string(instance)) return;
  var result = new ValidatorResult(instance, schema, options, ctx);
  var pattern = schema.pattern;
  try {
    var regexp = new RegExp(pattern, 'u');
  } catch(_e) {
    // In the event the stricter handling causes an error, fall back on the forgiving handling
    // DEPRECATED
    regexp = new RegExp(pattern);
  }
  if (!instance.match(regexp)) {
    result.addError({
      name: 'pattern',
      argument: schema.pattern,
      message: "does not match pattern " + JSON.stringify(schema.pattern.toString()),
    });
  }
  return result;
};

The code var regexp = new RegExp(pattern, 'u'); override the i modificator as case sensitive ignore.

    regexp = new RegExp(pattern);
  }
  console.log(regexp); // <<-- Test output final regexp
  if (!instance.match(regexp)) {

In the examples says can use regexp in plain method https://github.com/tdegrunt/jsonschema/blob/master/examples/all.js#L207 :

"validatePattern2": {
      "type": "string",
      "pattern": /str/
    },

But the documentation does not indicate that in these cases you can or cannot use modifiers like case insensitive in pattern object.