проверить JSON, у которого есть разрывы строк? - PullRequest
1 голос
/ 11 июня 2019

Как правильно проверить документ JSON со значениями, содержащими разрывы строк, \n, используя ajv ?

Упрощенный пример:

  • Схема JSON определяет документ, имеющий единственное свойство с именем key, которое принимает значение string (схема была выведена путем отправки {"key":"value"} в https://jsonschema.net)
  • Объект JavaScript сериализуется с использованием JSON.stringify(). Как следствие, символы новой строки, такие как \n, экранируются, т.е. \\n
  • Функция Ajv validate () вызывается для проверки сериализованной строки

Отрывок:

// JSON schema definition
const schema = {
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "title": "The Root Schema",
  "required": [
    "key"
  ],
  "properties": {
    "key": {
      "$id": "#/properties/key",
      "type": "string",
      "title": "The Key Schema",
      "default": "",
      "examples": [
        "value"
      ],
      "pattern": "^(.*)$"
    }
  }
};

// a JavaScript object that has a line break
const data = { key: 'a string\nwith a line break' };

// serialize to JSON
const json = JSON.stringify(data);
// json === "{\"key\":\"a string\\nwith a line break\"}"

// validate
const Ajv = require('ajv');
const ajv = new Ajv();
const valid = ajv.validate(schema, json);

// print results
console.info('Valid:', valid);
console.info('Errors:', ajv.errors);

Я ожидал, что это сработает, но выясняется, что во время выполнения происходит сбой проверки:

Valid: false
Errors: [
  {
    keyword: 'type',
    dataPath: '',
    schemaPath: '#/type',
    params: { type: 'object' },
    message: 'should be object'
  }
]

Насколько я понимаю, это потому, что json - это string, тогда как определение схемы гласит, что это должно быть object.

Я также пытался десериализовать строку JSON, например, ajv.validate(schema, JSON.parse(json));, но также не работает:

Valid: false
Errors: [
  {
    keyword: 'pattern',
    dataPath: '.key',
    schemaPath: '#/properties/key/pattern',
    params: { pattern: '^(.*)$' },
    message: 'should match pattern "^(.*)$"'
  }
]

Это имеет смысл, поскольку JSON.parse() возвращает объект JavaScript, который не является JSON (например, ключи не заключены в кавычки и, что важно, для значений строки этого вопроса с неэкранированными \n символами).

Зависимость: ajv 6.10.0

1 Ответ

0 голосов
/ 12 июня 2019

Оказывается, я использовал неправильный шаблон регулярных выражений. . соответствует любому символу , кроме новой строки . Чтобы обойти это, я изменил шаблон на [\s\S], где класс символов \s соответствует «любому символу пробела», а класс символов \S - его отрицание, «любой символ без пробела». Более того, поскольку шаблон определен в значении объекта JavaScript, обратные слэши в \s и \S также должны быть экранированы, т.е. [\\s\\S]. Следовательно, определение схемы должно быть следующим:

const schema = {
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "title": "The Root Schema",
  "required": [
    "key"
  ],
  "properties": {
    "key": {
      "$id": "#/properties/key",
      "type": "string",
      "title": "The Key Schema",
      "default": "",
      "examples": [
        "value"
      ],
      "pattern": "^([\\s\\S]*)$"
    }
  }
};

См. Также этот ответ и онлайн-тестер регулярных выражений

...