使用转义字符的模式进行JSON(模式)验证失败

14

以下 JSON 对象是有效的:

{
    "foo": "bar",
    "pattern": "^(\/?[-a-zA-Z0-9_.]+)+$"
}

然而这一个是

{
    "foo": "bar",
    "pattern": "^(\/?[-a-zA-Z0-9_.]+)+\.jpg$"
}

这是转义后的 (\.),但我不明白为什么这不是有效的JSON。我需要在我的实际JSON模式中包含这样的模式。那里的正则表达式要复杂得多,并且无论如何都不能错过转义,特别是点。

顺便说一下,在字符类中转义连字符(例如[a-z\-])也会导致验证失败。

我该如何修复?

编辑:我使用了http://jsonlint.com和几个node库。

2个回答

17

这里需要进行双重转义。在 JSON 中,反斜杠是转义字符,因此您不能对点进行转义(它将被视为转义字符)。相反,您需要对那个反斜杠进行转义,以便您的正则表达式呈现出 \. 的样式(JSON 在转义后期望一个保留字符,例如引号或另一个反斜杠等)。

// passes validation
{
    "foo": "bar",
    "pattern": "^(/?[-a-zA-Z0-9_.]+)+\\.jpg$"
}

0

您可以使用 ajv-keywords 中的 regexp

import Ajv from 'ajv';
import AjvKeywords from 'ajv-keywords';
// ajv-errors needed for errorMessage
import AjvErrors from 'ajv-errors';

const ajv = new Ajv.default({ allErrors: true });

AjvKeywords(ajv, "regexp");
AjvErrors(ajv);

// modification of regex by requiring Z https://www.regextester.com/97766
const ISO8601UTCRegex = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?Z$/;

const typeISO8601UTC = {
  "type": "string",
  "regexp": ISO8601UTCRegex.toString(),
  "errorMessage": "must be string of format 1970-01-01T00:00:00Z. Got ${0}",
};

const schema = {
  type: "object",
  properties: {
    foo: { type: "number", minimum: 0 },
    timestamp: typeISO8601UTC,
  },
  required: ["foo", "timestamp"],
  additionalProperties: false,
};

const validate = ajv.compile(schema);

const data = { foo: 1, timestamp: "2020-01-11T20:28:00" }

if (validate(data)) {
  console.log(JSON.stringify(data, null, 2));
} else {
  console.log(JSON.stringify(validate.errors, null, 2));
}

https://github.com/rofrol/ajv-regexp-errormessage-example


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接