Skip to content

Commit

Permalink
to-jsonschema: Fix pattern keyword for strings
Browse files Browse the repository at this point in the history
JSON Schema supports the `pattern` keyword to express constraints for
strings as regular expressions [1].

Update the to-jsonschema module to return `pattern` as a string instead
of as a RegExp object. This ensures a valid `pattern` in the generated
JSON Schema.

Note that JSON Schema doesn't support regular expression flags in its
patterns.

[1] https://json-schema.org/understanding-json-schema/reference/regular_expressions.html
  • Loading branch information
msmolens committed Jun 21, 2023
1 parent 4bcc017 commit f72790e
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 9 deletions.
21 changes: 21 additions & 0 deletions features/to-jsonschema.feature
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,24 @@ Scenario: Object
Scenario: Literal union
When mapping to JSON schema "'a'|#b|`c`|\"d\""
Then the resulting schema is { "enum": ["a", "b", "c", "d"] }

Scenario: Regular expression
When mapping to JSON schema /^\d+$/
Then the resulting schema is
"""
{
"pattern": "^\\d+$",
"type": "string"
}
"""

# JSON Schema doesn't support regular expression flags
Scenario: Regular expression with flags
When mapping to JSON schema /^[A-Z]+$/i
Then the resulting schema is
"""
{
"pattern": "^[A-Z]+$",
"type": "string"
}
"""
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mural-schema",
"version": "3.4.0",
"version": "3.4.1",
"description": "A JSON validation library using pure JSON schemas",
"main": "index.js",
"types": "index.d.ts",
Expand Down
24 changes: 18 additions & 6 deletions src/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,24 @@ import toJsonSchema, { astToJsonSchema } from './to-jsonschema';

astToJsonSchema; // pin down this reference

const parseJSON = (s: string) =>
s === 'undefined'
? undefined
: s.startsWith('/') && s.endsWith('/') && s.length > 1
? new RegExp(s.substring(1, s.length - 1))
: JSON.parse(s);
// Regular expression to match a regular expression literal
const regExpRe = /^\/(.*)\/[dgimsuy]*$/;

const parseJSON = (s: string) => {
// Literal 'undefined'
if (s === 'undefined') {
return undefined;
}

// Regular expression
const result = regExpRe.exec(s);
const pattern = result ? result[1] : null;
if (pattern) {
return new RegExp(pattern);
}

return JSON.parse(s);
};

const opts: S.ParseOptions = {
customTypes: {
Expand Down
2 changes: 1 addition & 1 deletion src/to-jsonschema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const mapObject = (ast: ObjectAst, options: Options): JsonSchemaObject => ({
});

const mapRegExp = (ast: RegExpAst): JsonSchemaString => ({
pattern: ast.value,
pattern: ast.value.source,
type: 'string',
});

Expand Down
2 changes: 1 addition & 1 deletion src/to-jsonschema/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface JsonSchemaObject {

export interface JsonSchemaString {
type: 'string';
pattern?: RegExp;
pattern?: string;
}

interface JsonSchemaUnion {
Expand Down

0 comments on commit f72790e

Please sign in to comment.