Skip to content

Commit c50ec21

Browse files
authored
fix: array of objects with properties (#17)
1 parent 91457f5 commit c50ec21

File tree

5 files changed

+138
-26
lines changed

5 files changed

+138
-26
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"type": "object",
3+
"xml": {
4+
"name": "Pet"
5+
},
6+
"properties": {
7+
"propertyIsArrayOfObjects": {
8+
"type": [
9+
"array"
10+
],
11+
"items": {
12+
"type": "object",
13+
"properties": {
14+
"ArrayObjectProperty": {
15+
"type": "string"
16+
}
17+
}
18+
}
19+
}
20+
}
21+
}

src/utils/__tests__/__snapshots__/renderSchema.spec.ts.snap

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,82 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`renderSchema util should match array-of-objects.json 1`] = `
4+
Array [
5+
Object {
6+
"canHaveChildren": true,
7+
"id": "random-id",
8+
"level": 0,
9+
"metadata": Object {
10+
"additionalProperties": undefined,
11+
"annotations": Object {},
12+
"enum": undefined,
13+
"id": "random-id",
14+
"path": Array [],
15+
"patternProperties": undefined,
16+
"properties": Object {
17+
"propertyIsArrayOfObjects": Object {
18+
"items": Object {
19+
"properties": Object {
20+
"ArrayObjectProperty": Object {
21+
"type": "string",
22+
},
23+
},
24+
"type": "object",
25+
},
26+
"type": Array [
27+
"array",
28+
],
29+
},
30+
},
31+
"type": "object",
32+
"validations": Object {},
33+
},
34+
"name": "",
35+
},
36+
Object {
37+
"id": "random-id",
38+
"level": 1,
39+
"metadata": Object {
40+
"additionalItems": undefined,
41+
"annotations": Object {},
42+
"enum": undefined,
43+
"id": "random-id",
44+
"items": undefined,
45+
"name": "propertyIsArrayOfObjects",
46+
"path": Array [
47+
"properties",
48+
"propertyIsArrayOfObjects",
49+
],
50+
"required": false,
51+
"subtype": "object",
52+
"type": "array",
53+
"validations": Object {},
54+
},
55+
"name": "",
56+
},
57+
Object {
58+
"id": "random-id",
59+
"level": 3,
60+
"metadata": Object {
61+
"annotations": Object {},
62+
"enum": undefined,
63+
"id": "random-id",
64+
"name": "ArrayObjectProperty",
65+
"path": Array [
66+
"properties",
67+
"propertyIsArrayOfObjects",
68+
"items",
69+
"ArrayObjectProperty",
70+
],
71+
"required": false,
72+
"type": "string",
73+
"validations": Object {},
74+
},
75+
"name": "",
76+
},
77+
]
78+
`;
79+
380
exports[`renderSchema util should match combiner-schema.json 1`] = `
481
Array [
582
Object {

src/utils/__tests__/renderSchema.spec.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@ jest.mock('../assignId', () => ({
99
}));
1010

1111
describe('renderSchema util', () => {
12-
it.each([['default-schema.json', ''], ['ref/original.json', 'ref/resolved.json'], ['combiner-schema.json', '']])(
13-
'should match %s',
14-
(schema, dereferenced) => {
15-
expect(
16-
Array.from(
17-
renderSchema(
18-
JSON.parse(fs.readFileSync(path.resolve(BASE_PATH, schema), 'utf-8')),
19-
dereferenced ? JSON.parse(fs.readFileSync(path.resolve(BASE_PATH, dereferenced), 'utf-8')) : undefined
20-
)
12+
it.each([
13+
['default-schema.json', ''],
14+
['ref/original.json', 'ref/resolved.json'],
15+
['combiner-schema.json', ''],
16+
['array-of-objects.json', ''],
17+
])('should match %s', (schema, dereferenced) => {
18+
expect(
19+
Array.from(
20+
renderSchema(
21+
JSON.parse(fs.readFileSync(path.resolve(BASE_PATH, schema), 'utf-8')),
22+
dereferenced ? JSON.parse(fs.readFileSync(path.resolve(BASE_PATH, dereferenced), 'utf-8')) : undefined
2123
)
22-
).toMatchSnapshot();
23-
}
24-
);
24+
)
25+
).toMatchSnapshot();
26+
});
2527
});

src/utils/renderSchema.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,22 +103,26 @@ export const renderSchema: Walker = function*(schema, dereferencedSchema, level
103103
(node as IArrayNode).additionalItems && { additional: (node as IArrayNode).additionalItems }),
104104
},
105105
} as SchemaTreeListNode;
106-
107106
if (Array.isArray(schema.items)) {
108107
for (const [i, property] of schema.items.entries()) {
109108
yield* renderSchema(property, dereferencedSchema, level + 1, {
110109
path: [...path, 'items', i],
111110
});
112111
}
113-
} else if (meta.subtype === 'object' && schema.items) {
114-
yield* getProperties(schema.items, dereferencedSchema, level + 1, {
115-
...meta,
116-
path: [...path, 'items'],
117-
});
118-
} else if (meta.subtype === 'array' && schema.items) {
119-
yield* renderSchema(schema.items, dereferencedSchema, level + 1, {
120-
path,
121-
});
112+
} else if (schema.items) {
113+
switch (baseNode.metadata && baseNode.metadata.subtype) {
114+
case SchemaKind.Object:
115+
yield* getProperties(schema.items, dereferencedSchema, level + 1, {
116+
...meta,
117+
path: [...path, 'items'],
118+
});
119+
break;
120+
case SchemaKind.Array:
121+
yield* renderSchema(schema.items, dereferencedSchema, level + 1, {
122+
path,
123+
});
124+
break;
125+
}
122126
}
123127
} else if ('properties' in node) {
124128
// special case :P, it's

src/utils/walk.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const getCombiner = (node: JSONSchema4): JSONSchema4CombinerName | void => {
2020
};
2121

2222
function assignNodeSpecificFields(base: IBaseNode, node: JSONSchema4) {
23-
switch (node.type) {
23+
switch (getType(node)) {
2424
case SchemaKind.Array:
2525
(base as IArrayNode).items = node.array;
2626
(base as IArrayNode).additionalItems = node.additionalItems;
@@ -33,20 +33,28 @@ function assignNodeSpecificFields(base: IBaseNode, node: JSONSchema4) {
3333
}
3434
}
3535

36+
function getType(node: JSONSchema4) {
37+
if (Array.isArray(node.type)) {
38+
return node.type.length === 1 ? node.type[0] : node.type;
39+
}
40+
41+
return node.type;
42+
}
43+
3644
function processNode(node: JSONSchema4): SchemaNode | void {
3745
const combiner = getCombiner(node);
3846

3947
if (node.type !== undefined && combiner === undefined) {
4048
const base: IBaseNode = {
4149
id: assignId(node),
42-
type: node.type,
50+
type: getType(node),
4351
validations: getValidations(node),
4452
annotations: getAnnotations(node),
4553
enum: node.enum,
4654
};
4755

48-
if (Array.isArray(node.type)) {
49-
if (node.type.includes('object')) {
56+
if (Array.isArray(base.type)) {
57+
if (base.type.includes('object')) {
5058
// special case :P
5159
assignNodeSpecificFields(base, {
5260
...node,

0 commit comments

Comments
 (0)