Skip to content

Commit c2f29e4

Browse files
author
ochafik
committed
json: better suport for "type" arrays (e.g. {"type": ["array", "null"], "items": {"type": "string"}})
1 parent fd5ea0f commit c2f29e4

File tree

4 files changed

+37
-3
lines changed

4 files changed

+37
-3
lines changed

common/json-schema-to-grammar.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,9 @@ class SchemaConverter {
594594
} else if (schema_type.is_array()) {
595595
std::vector<json> schema_types;
596596
for (const auto & t : schema_type) {
597-
schema_types.push_back({{"type", t}});
597+
json schema_copy(schema);
598+
schema_copy["type"] = t;
599+
schema_types.push_back(schema_copy);
598600
}
599601
return _add_rule(rule_name, _generate_union_rule(name, schema_types));
600602
} else if (schema.contains("const")) {

examples/json_schema_to_grammar.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ def visit(self, schema, name):
358358
return self._add_rule(rule_name, self._generate_union_rule(name, schema.get('oneOf') or schema['anyOf']))
359359

360360
elif isinstance(schema_type, list):
361-
return self._add_rule(rule_name, self._generate_union_rule(name, [{'type': t} for t in schema_type]))
361+
return self._add_rule(rule_name, self._generate_union_rule(name, [{**schema, 'type': t} for t in schema_type]))
362362

363363
elif 'const' in schema:
364364
return self._add_rule(rule_name, self._generate_constant_rule(schema['const']))

examples/server/public/json-schema-to-grammar.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ export class SchemaConverter {
363363
} else if (schema.oneOf || schema.anyOf) {
364364
return this._addRule(ruleName, this._generateUnionRule(name, schema.oneOf || schema.anyOf));
365365
} else if (Array.isArray(schemaType)) {
366-
return this._addRule(ruleName, this._generateUnionRule(name, schemaType.map(t => ({ type: t }))));
366+
return this._addRule(ruleName, this._generateUnionRule(name, schemaType.map(t => ({...schema, type: t}))));
367367
} else if ('const' in schema) {
368368
return this._addRule(ruleName, this._generateConstantRule(schema.const));
369369
} else if ('enum' in schema) {

tests/test-json-schema-to-grammar.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,38 @@ static void test_all(const std::string & lang, std::function<void(const TestCase
276276
)"""
277277
});
278278

279+
test({
280+
SUCCESS,
281+
"string array",
282+
R"""({
283+
"type": "array",
284+
"prefixItems": { "type": "string" }
285+
})""",
286+
R"""(
287+
char ::= [^"\\] | "\\" (["\\/bfnrt] | "u" [0-9a-fA-F]{4})
288+
root ::= "[" space (string ("," space string)*)? "]" space
289+
space ::= " "?
290+
string ::= "\"" char* "\"" space
291+
)"""
292+
});
293+
294+
test({
295+
SUCCESS,
296+
"nullable string array",
297+
R"""({
298+
"type": ["array", "null"],
299+
"prefixItems": { "type": "string" }
300+
})""",
301+
R"""(
302+
alternative-0 ::= "[" space (string ("," space string)*)? "]" space
303+
char ::= [^"\\] | "\\" (["\\/bfnrt] | "u" [0-9a-fA-F]{4})
304+
null ::= "null" space
305+
root ::= alternative-0 | null
306+
space ::= " "?
307+
string ::= "\"" char* "\"" space
308+
)"""
309+
});
310+
279311
test({
280312
SUCCESS,
281313
"tuple1",

0 commit comments

Comments
 (0)