Skip to content

Commit e35c261

Browse files
authored
support for recursion in arrays (#363)
1 parent 0bdc908 commit e35c261

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed

index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ function mergeLocation (source, dest) {
4747
}
4848
}
4949

50+
const referenceSerializersMap = new Map()
51+
5052
function build (schema, options) {
53+
referenceSerializersMap.clear()
5154
options = options || {}
5255
isValidSchema(schema)
5356
if (options.schema) {
@@ -144,6 +147,8 @@ function build (schema, options) {
144147
return dependenciesName
145148
}
146149

150+
referenceSerializersMap.clear()
151+
147152
return (Function.apply(null, dependenciesName).apply(null, dependencies))
148153
}
149154

@@ -969,8 +974,18 @@ function buildArray (location, code, name, key = null) {
969974
schema = location.schema
970975
schema[fjsCloned] = true
971976
}
977+
972978
location = refFinder(schema.items.$ref, location)
973979
schema.items = location.schema
980+
981+
if (referenceSerializersMap.has(schema.items)) {
982+
code += `
983+
return ${referenceSerializersMap.get(schema.items)}(obj)
984+
}
985+
`
986+
return code
987+
}
988+
referenceSerializersMap.set(schema.items, name)
974989
}
975990

976991
let result = { code: '', laterCode: '' }

test/recursion.test.js

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
'use strict'
2+
3+
const test = require('tap').test
4+
const build = require('..')
5+
6+
test('can stringify recursive directory tree (issue #181)', (t) => {
7+
t.plan(1)
8+
9+
const schema = {
10+
definitions: {
11+
directory: {
12+
type: 'object',
13+
properties: {
14+
name: { type: 'string' },
15+
subDirectories: {
16+
type: 'array',
17+
items: { $ref: '#/definitions/directory' },
18+
default: []
19+
}
20+
}
21+
}
22+
},
23+
type: 'array',
24+
items: { $ref: '#/definitions/directory' }
25+
}
26+
const stringify = build(schema)
27+
28+
t.equal(stringify([
29+
{ name: 'directory 1', subDirectories: [] },
30+
{
31+
name: 'directory 2',
32+
subDirectories: [
33+
{ name: 'directory 2.1', subDirectories: [] },
34+
{ name: 'directory 2.2', subDirectories: [] }
35+
]
36+
}
37+
]), '[{"name":"directory 1","subDirectories":[]},{"name":"directory 2","subDirectories":[{"name":"directory 2.1","subDirectories":[]},{"name":"directory 2.2","subDirectories":[]}]}]')
38+
})
39+
40+
test('can stringify when recursion in external schema', t => {
41+
t.plan(1)
42+
43+
const referenceSchema = {
44+
$id: 'person',
45+
type: 'object',
46+
properties: {
47+
name: { type: 'string' },
48+
children: {
49+
type: 'array',
50+
items: { $ref: '#' }
51+
}
52+
}
53+
}
54+
55+
const schema = {
56+
$id: 'mainSchema',
57+
type: 'object',
58+
properties: {
59+
people: {
60+
$ref: 'person'
61+
}
62+
}
63+
}
64+
const stringify = build(schema, {
65+
schema: {
66+
[referenceSchema.$id]: referenceSchema
67+
}
68+
})
69+
70+
const value = stringify({ people: { name: 'Elizabeth', children: [{ name: 'Charles' }] } })
71+
t.equal(value, '{"people":{"name":"Elizabeth","children":[{"name":"Charles"}]}}')
72+
})
73+
74+
test('use proper serialize function', t => {
75+
t.plan(1)
76+
77+
const personSchema = {
78+
$id: 'person',
79+
type: 'object',
80+
properties: {
81+
name: { type: 'string' },
82+
children: {
83+
type: 'array',
84+
items: { $ref: '#' }
85+
}
86+
}
87+
}
88+
89+
const directorySchema = {
90+
$id: 'directory',
91+
type: 'object',
92+
properties: {
93+
name: { type: 'string' },
94+
subDirectories: {
95+
type: 'array',
96+
items: { $ref: '#' },
97+
default: []
98+
}
99+
}
100+
}
101+
102+
const schema = {
103+
$id: 'mainSchema',
104+
type: 'object',
105+
properties: {
106+
people: { $ref: 'person' },
107+
directory: { $ref: 'directory' }
108+
}
109+
}
110+
const stringify = build(schema, {
111+
schema: {
112+
[personSchema.$id]: personSchema,
113+
[directorySchema.$id]: directorySchema
114+
}
115+
})
116+
117+
const value = stringify({
118+
people: {
119+
name: 'Elizabeth',
120+
children: [{
121+
name: 'Charles',
122+
children: [{ name: 'William', children: [{ name: 'George' }, { name: 'Charlotte' }] }, { name: 'Harry' }]
123+
}]
124+
},
125+
directory: {
126+
name: 'directory 1',
127+
subDirectories: [
128+
{ name: 'directory 1.1', subDirectories: [] },
129+
{
130+
name: 'directory 1.2',
131+
subDirectories: [{ name: 'directory 1.2.1' }, { name: 'directory 1.2.2' }]
132+
}
133+
]
134+
}
135+
})
136+
t.equal(value, '{"people":{"name":"Elizabeth","children":[{"name":"Charles","children":[{"name":"William","children":[{"name":"George"},{"name":"Charlotte"}]},{"name":"Harry"}]}]},"directory":{"name":"directory 1","subDirectories":[{"name":"directory 1.1","subDirectories":[]},{"name":"directory 1.2","subDirectories":[{"name":"directory 1.2.1","subDirectories":[]},{"name":"directory 1.2.2","subDirectories":[]}]}]}}')
137+
})

0 commit comments

Comments
 (0)