From 618247885c7d367704a951993157b4630781dfec Mon Sep 17 00:00:00 2001 From: ochafik Date: Mon, 18 Mar 2024 00:13:58 +0000 Subject: [PATCH] json: test/fix top-level anyOf --- examples/json-schema-to-grammar.py | 2 +- examples/server/json-schema-to-grammar.cpp | 7 +- .../server/json-schema-to-grammar.mjs.hpp | 5 +- .../server/public/json-schema-to-grammar.mjs | 2 +- examples/ts-type-to-grammar.sh | 2 +- tests/test-json-schema-to-grammar.cpp | 73 +++++++++++++++++++ 6 files changed, 84 insertions(+), 7 deletions(-) diff --git a/examples/json-schema-to-grammar.py b/examples/json-schema-to-grammar.py index ea54c88bc..5ad8e52f6 100755 --- a/examples/json-schema-to-grammar.py +++ b/examples/json-schema-to-grammar.py @@ -128,7 +128,7 @@ class SchemaConverter: def _generate_union_rule(self, name, alt_schemas): return ' | '.join(( - self.visit(alt_schema, f'{name}{"-" if name else ""}{i}') + self.visit(alt_schema, f'{name}{"-" if name else "alternative-"}{i}') for i, alt_schema in enumerate(alt_schemas) )) diff --git a/examples/server/json-schema-to-grammar.cpp b/examples/server/json-schema-to-grammar.cpp index 640890d46..bb2c58d48 100644 --- a/examples/server/json-schema-to-grammar.cpp +++ b/examples/server/json-schema-to-grammar.cpp @@ -170,7 +170,7 @@ private: string _generate_union_rule(const string& name, const vector& alt_schemas) { vector rules; for (size_t i = 0; i < alt_schemas.size(); i++) { - rules.push_back(visit(alt_schemas[i], name + (name.empty() ? "" : "-") + to_string(i))); + rules.push_back(visit(alt_schemas[i], name + (name.empty() ? "alternative-" : "-") + to_string(i))); } return join(rules.begin(), rules.end(), " | "); } @@ -596,7 +596,10 @@ public: properties.emplace_back(prop.key(), prop.value()); } } - return _add_rule(rule_name, _build_object_rule(properties, required, name, schema["additionalProperties"])); + return _add_rule(rule_name, + _build_object_rule( + properties, required, name, + schema.contains("additionalProperties") ? schema["additionalProperties"] : json())); } else if ((schema_type.is_null() || schema_type == "object") && schema.contains("allOf")) { unordered_set required; vector> properties; diff --git a/examples/server/json-schema-to-grammar.mjs.hpp b/examples/server/json-schema-to-grammar.mjs.hpp index f1a4a9fb4..e6dacb035 100644 --- a/examples/server/json-schema-to-grammar.mjs.hpp +++ b/examples/server/json-schema-to-grammar.mjs.hpp @@ -406,7 +406,8 @@ unsigned char json_schema_to_grammar_mjs[] = { 0x73, 0x69, 0x74, 0x28, 0x61, 0x6c, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2c, 0x20, 0x60, 0x24, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3f, 0x3f, 0x20, 0x27, 0x27, 0x7d, 0x24, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x20, - 0x3f, 0x20, 0x27, 0x2d, 0x27, 0x20, 0x3a, 0x20, 0x27, 0x27, 0x7d, 0x24, + 0x3f, 0x20, 0x27, 0x2d, 0x27, 0x20, 0x3a, 0x20, 0x27, 0x61, 0x6c, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x27, 0x7d, 0x24, 0x7b, 0x69, 0x7d, 0x60, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x6a, 0x6f, 0x69, 0x6e, 0x28, 0x27, 0x20, 0x7c, 0x20, 0x27, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x5f, 0x76, @@ -1662,4 +1663,4 @@ unsigned char json_schema_to_grammar_mjs[] = { 0x61, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x2c, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x7d, 0x0a }; -unsigned int json_schema_to_grammar_mjs_len = 19942; +unsigned int json_schema_to_grammar_mjs_len = 19954; diff --git a/examples/server/public/json-schema-to-grammar.mjs b/examples/server/public/json-schema-to-grammar.mjs index 59174bc6c..76fe5c64c 100644 --- a/examples/server/public/json-schema-to-grammar.mjs +++ b/examples/server/public/json-schema-to-grammar.mjs @@ -138,7 +138,7 @@ export class SchemaConverter { _generateUnionRule(name, altSchemas) { return altSchemas - .map((altSchema, i) => this.visit(altSchema, `${name ?? ''}${name ? '-' : ''}${i}`)) + .map((altSchema, i) => this.visit(altSchema, `${name ?? ''}${name ? '-' : 'alternative-'}${i}`)) .join(' | '); } diff --git a/examples/ts-type-to-grammar.sh b/examples/ts-type-to-grammar.sh index db4881f26..82550855c 100755 --- a/examples/ts-type-to-grammar.sh +++ b/examples/ts-type-to-grammar.sh @@ -19,7 +19,7 @@ echo "export type MyType = $type" > "$DTS_FILE" # This is a fork of typescript-json-schema, actively maintained as of March 2024: # https://github.com/vega/ts-json-schema-generator -npx ts-json-schema-generator --unstable --no-top-ref --path "$DTS_FILE" --type MyType -e none | tee "$SCHEMA_FILE" >&2 +npx ts-json-schema-generator --unstable --no-top-ref --path "$DTS_FILE" --type MyType -e none > "$SCHEMA_FILE" # Alternative, not actively maintained as of March 2024: # https://github.com/YousefED/typescript-json-schema diff --git a/tests/test-json-schema-to-grammar.cpp b/tests/test-json-schema-to-grammar.cpp index 34bdcec49..87b5b655f 100755 --- a/tests/test-json-schema-to-grammar.cpp +++ b/tests/test-json-schema-to-grammar.cpp @@ -577,6 +577,79 @@ static void test_all(const string& lang, std::function ru )""" }); + test({ + SUCCESS, + "anyOf", + R"""({ + "anyOf": [ + {"$ref": "#/definitions/foo"}, + {"$ref": "#/definitions/bar"} + ], + "definitions": { + "foo": { + "properties": {"a": {"type": "number"}} + }, + "bar": { + "properties": {"b": {"type": "number"}} + } + }, + "type": "object" + })""", + R"""( + alternative-0 ::= foo + alternative-1 ::= bar + bar ::= "{" space (bar-b-kv )? "}" space + bar-b-kv ::= "\"b\"" space ":" space number + foo ::= "{" space (foo-a-kv )? "}" space + foo-a-kv ::= "\"a\"" space ":" space number + number ::= ("-"? ([0-9] | [1-9] [0-9]*)) ("." [0-9]+)? ([eE] [-+]? [0-9]+)? space + root ::= alternative-0 | alternative-1 + space ::= " "? + )""" + }); + + test({ + SUCCESS, + "mix of allOf, anyOf and $ref (similar to https://json.schemastore.org/tsconfig.json)", + R"""({ + "allOf": [ + {"$ref": "#/definitions/foo"}, + {"$ref": "#/definitions/bar"}, + { + "anyOf": [ + {"$ref": "#/definitions/baz"}, + {"$ref": "#/definitions/bam"} + ] + } + ], + "definitions": { + "foo": { + "properties": {"a": {"type": "number"}} + }, + "bar": { + "properties": {"b": {"type": "number"}} + }, + "bam": { + "properties": {"c": {"type": "number"}} + }, + "baz": { + "properties": {"d": {"type": "number"}} + } + }, + "type": "object" + })""", + R"""( + a-kv ::= "\"a\"" space ":" space number + b-kv ::= "\"b\"" space ":" space number + c-kv ::= "\"c\"" space ":" space number + d-kv ::= "\"d\"" space ":" space number + d-rest ::= ( "," space c-kv )? + number ::= ("-"? ([0-9] | [1-9] [0-9]*)) ("." [0-9]+)? ([eE] [-+]? [0-9]+)? space + root ::= "{" space a-kv "," space b-kv ( "," space ( d-kv d-rest | c-kv ) )? "}" space + space ::= " "? + )""" + }); + test({ SUCCESS, "conflicting names",