Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion packages/quicktype-core/src/rewrites/FlattenUnions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ export function flattenUnions(
.join(",");
}

function containsIntersection(t: Type, seen: Set<number>): boolean {
if (seen.has(t.index)) return false;
seen.add(t.index);

if (t instanceof IntersectionType) return true;
if (!(t instanceof UnionType)) return false;

return iterableSome(t.members, (m) => containsIntersection(m, seen));
}

function replace(
types: ReadonlySet<Type>,
builder: GraphRewriteBuilder<Type>,
Expand Down Expand Up @@ -86,7 +96,9 @@ export function flattenUnions(
trefs.map((tref) => derefTypeRef(tref, graph)),
);
if (
iterableSome(typesToUnify, (t) => t instanceof IntersectionType)
iterableSome(typesToUnify, (t) =>
containsIntersection(t, new Set()),
)
) {
trefs = trefs.map((tref) =>
builder.reconstituteType(derefTypeRef(tref, graph)),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"input": [
{
"content": "valid item"
},
["this array is not a valid item"]
]
}
20 changes: 20 additions & 0 deletions test/inputs/schema/nested-intersection-union.1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"input": [
{
"content": "hello",
"id": "item-1",
"output": "42",
"summary": "all fields present"
},
{
"content": "just a message"
},
{
"id": "item-2",
"output": "function result"
},
{
"summary": "just reasoning"
}
]
}
58 changes: 58 additions & 0 deletions test/inputs/schema/nested-intersection-union.schema
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
"input": {
"type": "array",
"items": {
"oneOf": [
{ "$ref": "#/definitions/Message" },
{ "$ref": "#/definitions/Item" }
]
}
}
},
"required": ["input"],
"definitions": {
"Message": {
"type": "object",
"properties": {
"content": { "type": "string" }
},
"required": ["content"]
},
"Item": {
"oneOf": [
{ "$ref": "#/definitions/FunctionOutput" },
{ "$ref": "#/definitions/ReasoningItem" }
]
},
"FunctionOutput": {
"allOf": [
{ "$ref": "#/definitions/BaseItem" },
{
"type": "object",
"properties": {
"output": { "type": "string" }
},
"required": ["output"]
}
]
},
"BaseItem": {
"type": "object",
"properties": {
"id": { "type": "string" }
},
"required": ["id"]
},
"ReasoningItem": {
"type": "object",
"properties": {
"summary": { "type": "string" }
},
"required": ["summary"]
}
}
}
3 changes: 3 additions & 0 deletions test/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ export const CJSONLanguage: Language = {
"class-with-additional.schema",
"go-schema-pattern-properties.schema",
"multi-type-enum.schema",
"nested-intersection-union.schema",
/* Constraints (min/max and regex) are not supported (for the current implementation, can be added later, should abord parsing and return NULL) */
"minmaxlength.schema",
"optional-const-ref.schema",
Expand Down Expand Up @@ -630,6 +631,8 @@ export const CPlusPlusLanguage: Language = {
skipSchema: [
// uses too much memory
"keyword-unions.schema",
// The generated deserializer accepts non-object values when all class properties are optional.
"nested-intersection-union.schema",
// Recursive top-level unions produce aliases that can refer to later aliases.
"recursive-union-flattening.schema",
],
Expand Down
Loading