json: basic support for reserved names {number:{number:{root:number}}}
This commit is contained in:
parent
daceced65e
commit
5714487830
4 changed files with 113 additions and 5 deletions
|
@ -35,6 +35,8 @@ DATE_RULES = {
|
||||||
'date-time-string': '"\\"" date-time "\\"" space',
|
'date-time-string': '"\\"" date-time "\\"" space',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RESERVED_NAMES = set(["root", *PRIMITIVE_RULES.keys(), *DATE_RULES.keys()])
|
||||||
|
|
||||||
INVALID_RULE_CHARS_RE = re.compile(r'[^a-zA-Z0-9-]+')
|
INVALID_RULE_CHARS_RE = re.compile(r'[^a-zA-Z0-9-]+')
|
||||||
GRAMMAR_LITERAL_ESCAPE_RE = re.compile(r'[\r\n"]')
|
GRAMMAR_LITERAL_ESCAPE_RE = re.compile(r'[\r\n"]')
|
||||||
GRAMMAR_RANGE_LITERAL_ESCAPE_RE = re.compile(r'[\r\n"\]\-\\]')
|
GRAMMAR_RANGE_LITERAL_ESCAPE_RE = re.compile(r'[\r\n"\]\-\\]')
|
||||||
|
@ -300,7 +302,7 @@ class SchemaConverter:
|
||||||
def visit(self, schema, name):
|
def visit(self, schema, name):
|
||||||
schema_type = schema.get('type')
|
schema_type = schema.get('type')
|
||||||
schema_format = schema.get('format')
|
schema_format = schema.get('format')
|
||||||
rule_name = name or 'root'
|
rule_name = name + '-' if name in RESERVED_NAMES else name or 'root'
|
||||||
|
|
||||||
if (ref := schema.get('$ref')) is not None:
|
if (ref := schema.get('$ref')) is not None:
|
||||||
return self._add_rule(rule_name, self._resolve_ref(ref))
|
return self._add_rule(rule_name, self._resolve_ref(ref))
|
||||||
|
|
|
@ -43,6 +43,16 @@ unordered_map<string, string> DATE_RULES = {
|
||||||
{"date-time-string", "\"\\\"\" date-time \"\\\"\" space"}
|
{"date-time-string", "\"\\\"\" date-time \"\\\"\" space"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool is_reserved_name(const string& name) {
|
||||||
|
static std::unordered_set<std::string> RESERVED_NAMES;
|
||||||
|
if (RESERVED_NAMES.empty()) {
|
||||||
|
RESERVED_NAMES.insert("root");
|
||||||
|
for (const auto &p : PRIMITIVE_RULES) RESERVED_NAMES.insert(p.first);
|
||||||
|
for (const auto &p : DATE_RULES) RESERVED_NAMES.insert(p.first);
|
||||||
|
}
|
||||||
|
return RESERVED_NAMES.find(name) != RESERVED_NAMES.end();
|
||||||
|
}
|
||||||
|
|
||||||
regex INVALID_RULE_CHARS_RE("[^a-zA-Z0-9-]+");
|
regex INVALID_RULE_CHARS_RE("[^a-zA-Z0-9-]+");
|
||||||
regex GRAMMAR_LITERAL_ESCAPE_RE("[\r\n\"]");
|
regex GRAMMAR_LITERAL_ESCAPE_RE("[\r\n\"]");
|
||||||
regex GRAMMAR_RANGE_LITERAL_ESCAPE_RE("[\r\n\"\\]\\-\\\\]");
|
regex GRAMMAR_RANGE_LITERAL_ESCAPE_RE("[\r\n\"\\]\\-\\\\]");
|
||||||
|
@ -523,7 +533,7 @@ public:
|
||||||
string visit(const json& schema, const string& name) {
|
string visit(const json& schema, const string& name) {
|
||||||
json schema_type = schema.contains("type") ? schema["type"] : json();
|
json schema_type = schema.contains("type") ? schema["type"] : json();
|
||||||
string schema_format = schema.contains("format") ? schema["format"].get<string>() : "";
|
string schema_format = schema.contains("format") ? schema["format"].get<string>() : "";
|
||||||
string rule_name = name.empty() ? "root" : name;
|
string rule_name = is_reserved_name(name) ? name + "-" : name.empty() ? "root" : name;
|
||||||
|
|
||||||
if (schema.contains("$ref")) {
|
if (schema.contains("$ref")) {
|
||||||
return _add_rule(rule_name, _resolve_ref(schema["$ref"]));
|
return _add_rule(rule_name, _resolve_ref(schema["$ref"]));
|
||||||
|
|
|
@ -26,6 +26,8 @@ const DATE_RULES = {
|
||||||
'date-time-string': '"\\"" date-time "\\"" space',
|
'date-time-string': '"\\"" date-time "\\"" space',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const RESERVED_NAMES = {'root': true, ...PRIMITIVE_RULES, ...DATE_RULES};
|
||||||
|
|
||||||
const INVALID_RULE_CHARS_RE = /[^\dA-Za-z-]+/g;
|
const INVALID_RULE_CHARS_RE = /[^\dA-Za-z-]+/g;
|
||||||
const GRAMMAR_LITERAL_ESCAPE_RE = /[\n\r"]/g;
|
const GRAMMAR_LITERAL_ESCAPE_RE = /[\n\r"]/g;
|
||||||
const GRAMMAR_RANGE_LITERAL_ESCAPE_RE = /[\n\r"\]\-\\]/g;
|
const GRAMMAR_RANGE_LITERAL_ESCAPE_RE = /[\n\r"\]\-\\]/g;
|
||||||
|
@ -326,7 +328,7 @@ export class SchemaConverter {
|
||||||
visit(schema, name) {
|
visit(schema, name) {
|
||||||
const schemaType = schema.type;
|
const schemaType = schema.type;
|
||||||
const schemaFormat = schema.format;
|
const schemaFormat = schema.format;
|
||||||
const ruleName = name || 'root';
|
const ruleName = name in RESERVED_NAMES ? name + '-' : name == '' ? 'root' : name;
|
||||||
|
|
||||||
const ref = schema.$ref;
|
const ref = schema.$ref;
|
||||||
if (ref !== undefined) {
|
if (ref !== undefined) {
|
||||||
|
|
|
@ -259,10 +259,61 @@ int main() {
|
||||||
)"""
|
)"""
|
||||||
});
|
});
|
||||||
|
|
||||||
|
run_all({
|
||||||
|
"object w/ required props",
|
||||||
|
R"""({
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"definitions": {}
|
||||||
|
})""",
|
||||||
|
R"""(
|
||||||
|
a-kv ::= "\"a\"" space ":" space string
|
||||||
|
b-kv ::= "\"b\"" space ":" space string
|
||||||
|
root ::= "{" space a-kv "," space b-kv "}" space
|
||||||
|
space ::= " "?
|
||||||
|
string ::= "\"" (
|
||||||
|
[^"\\] |
|
||||||
|
"\\" (["\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F])
|
||||||
|
)* "\"" space
|
||||||
|
)"""
|
||||||
|
});
|
||||||
|
|
||||||
|
run_all({
|
||||||
|
"1 optional",
|
||||||
|
R"""({
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
})""",
|
||||||
|
R"""(
|
||||||
|
a-kv ::= "\"a\"" space ":" space string
|
||||||
|
root ::= "{" space (a-kv )? "}" space
|
||||||
|
space ::= " "?
|
||||||
|
string ::= "\"" (
|
||||||
|
[^"\\] |
|
||||||
|
"\\" (["\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F])
|
||||||
|
)* "\"" space
|
||||||
|
)"""
|
||||||
|
});
|
||||||
|
|
||||||
run_all({
|
run_all({
|
||||||
"optionals",
|
"optionals",
|
||||||
R"""({
|
R"""({
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
|
@ -333,7 +384,6 @@ int main() {
|
||||||
run_all({
|
run_all({
|
||||||
"top-level $ref",
|
"top-level $ref",
|
||||||
R"""({
|
R"""({
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$ref": "#/definitions/MyType",
|
"$ref": "#/definitions/MyType",
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"MyType": {
|
"MyType": {
|
||||||
|
@ -362,4 +412,48 @@ int main() {
|
||||||
)"""
|
)"""
|
||||||
});
|
});
|
||||||
|
|
||||||
|
run_all({
|
||||||
|
"conflicting names",
|
||||||
|
R"""({
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"number": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"number": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"root": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"root"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"number"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"number"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"definitions": {}
|
||||||
|
})""",
|
||||||
|
R"""(
|
||||||
|
number ::= ("-"? ([0-9] | [1-9] [0-9]*)) ("." [0-9]+)? ([eE] [-+]? [0-9]+)? space
|
||||||
|
number- ::= "{" space number-number-kv "}" space
|
||||||
|
number-kv ::= "\"number\"" space ":" space number-
|
||||||
|
number-number ::= "{" space number-number-root-kv "}" space
|
||||||
|
number-number-kv ::= "\"number\"" space ":" space number-number
|
||||||
|
number-number-root-kv ::= "\"root\"" space ":" space number
|
||||||
|
root ::= "{" space number-kv "}" space
|
||||||
|
space ::= " "?
|
||||||
|
)"""
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue