diff --git a/common/json-schema-to-grammar.cpp b/common/json-schema-to-grammar.cpp index 0aee51b26e84..dc7a017443b0 100644 --- a/common/json-schema-to-grammar.cpp +++ b/common/json-schema-to-grammar.cpp @@ -908,6 +908,16 @@ class common_schema_converter { } std::string visit(const json & schema, const std::string & name) { + // An empty union ("anyOf": [], "oneOf": [] or "type": []) has no alternatives to build a rule from; it used to + // produce an empty rule that the grammar parser rejects, failing the whole request. Schema generators do emit + // it, so drop the keyword and convert the rest of the schema. + for (const char * key : {"oneOf", "anyOf", "type"}) { + if (schema.is_object() && schema.contains(key) && schema.at(key).is_array() && schema.at(key).empty()) { + json rest = schema; + rest.erase(key); + return visit(rest, name); + } + } json schema_type = schema.contains("type") ? schema["type"] : json(); std::string schema_format = schema.contains("format") ? schema["format"].get() : ""; std::string rule_name = is_reserved_name(name) ? name + "-" : name.empty() ? "root" : name; diff --git a/examples/json_schema_to_grammar.py b/examples/json_schema_to_grammar.py index 83abd259da57..7a8c7463595f 100755 --- a/examples/json_schema_to_grammar.py +++ b/examples/json_schema_to_grammar.py @@ -566,6 +566,11 @@ def _generate_constant_rule(self, value): return self._format_literal(json.dumps(value)) def visit(self, schema, name): + # An empty union ("anyOf": [], "oneOf": [] or "type": []) has no alternatives to build a rule from; drop the + # keyword and convert the rest of the schema (same as the C++ converter). + for key in ('oneOf', 'anyOf', 'type'): + if isinstance(schema, dict) and isinstance(schema.get(key), list) and not schema[key]: + return self.visit({k: v for k, v in schema.items() if k != key}, name) schema_type = schema.get('type') schema_format = schema.get('format') rule_name = name + '-' if name in RESERVED_NAMES else name or 'root' diff --git a/tests/test-json-schema-to-grammar.cpp b/tests/test-json-schema-to-grammar.cpp index 214dbe1993b8..ef1242aaaf8a 100755 --- a/tests/test-json-schema-to-grammar.cpp +++ b/tests/test-json-schema-to-grammar.cpp @@ -1214,6 +1214,109 @@ static void test_all(const std::string & lang, std::function