Skip to content

Commit a91cae9

Browse files
authored
Merge pull request #244 from open-rpc/fix/json-schema-nested-arrays
fix: handle recursive json schema
2 parents 41ed7d3 + e2fb491 commit a91cae9

File tree

7 files changed

+479
-178
lines changed

7 files changed

+479
-178
lines changed
16.1 KB
Binary file not shown.

package-lock.json

Lines changed: 30 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/JSONSchema/JSONSchema.tsx

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import React, { Component } from "react";
2-
import { Typography } from "@material-ui/core";
32
import _ from "lodash";
43
import JSONSchemaFields from "./fields/JSONSchemaFields";
5-
import PrimitiveField from "./fields/JSONSchemaPrimitiveField";
64
import { JSONSchema4 } from "json-schema";
75

86
interface IProps {
@@ -12,44 +10,7 @@ interface IProps {
1210
class JSONSchema extends Component<IProps> {
1311
public render() {
1412
const { schema } = this.props;
15-
if (!schema) { return null; }
16-
if (_.isEmpty(schema)) { return null; }
17-
if (schema && !schema.properties && schema.oneOf) {
18-
return (
19-
<>
20-
{schema.oneOf &&
21-
<>
22-
<Typography variant="body1">one of</Typography>
23-
{schema.oneOf.map((item) => {
24-
return (
25-
<JSONSchema schema={item} />
26-
);
27-
})}
28-
</>
29-
}
30-
</>
31-
);
32-
}
33-
let arrayWithItems = schema && schema.type === "array" && (schema.items || schema.contains);
34-
if (arrayWithItems) {
35-
arrayWithItems = _.isArray(arrayWithItems) ? arrayWithItems : [arrayWithItems];
36-
return (
37-
<>
38-
<Typography variant="body1">array of</Typography>
39-
<JSONSchemaFields schema={schema} />
40-
{arrayWithItems.map((item: JSONSchema4) => {
41-
return (
42-
<JSONSchema schema={item} />
43-
);
44-
})}
45-
</>
46-
);
47-
}
48-
if (schema && schema.properties) {
49-
return <JSONSchemaFields schema={schema} />;
50-
}
51-
52-
return <PrimitiveField schema={schema} />;
13+
return <JSONSchemaFields schema={schema} />;
5314
}
5415
}
5516

src/JSONSchema/SchemaRenderer.tsx

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import React from "react";
2+
import { JSONSchema4 } from "json-schema";
3+
import { TableRow, TableCell, Typography } from "@material-ui/core";
4+
import JSONSchemaFields from "./fields/JSONSchemaFields";
5+
import _ from "lodash";
6+
import { grey, green, purple, yellow, blue } from "@material-ui/core/colors";
7+
8+
interface IProps {
9+
schema: JSONSchema4;
10+
required?: boolean;
11+
name?: string;
12+
}
13+
14+
const styles = {
15+
cellWidth: {
16+
width: "70px",
17+
},
18+
};
19+
20+
const SchemaRenderer: React.FC<IProps> = ({ schema, required, name }) => {
21+
if (schema.anyOf) {
22+
return (
23+
<TableRow>
24+
<TableCell colSpan={1} style={styles.cellWidth}>
25+
{schema.title || name}
26+
</TableCell>
27+
<TableCell colSpan={1} style={styles.cellWidth}>
28+
<Typography variant="body1" color="primary">any of</Typography>
29+
</TableCell>
30+
<TableCell colSpan={5}>
31+
{schema.anyOf.map((p, i) => <JSONSchemaFields schema={p} key={i} />)}
32+
</TableCell>
33+
</TableRow>
34+
);
35+
}
36+
if (schema.allOf) {
37+
return (
38+
<TableRow>
39+
<TableCell colSpan={1} style={styles.cellWidth}>
40+
{schema.title || name}
41+
</TableCell>
42+
<TableCell colSpan={1} style={styles.cellWidth}>
43+
<Typography variant="body1" color="primary">all of</Typography>
44+
</TableCell>
45+
<TableCell colSpan={5}>
46+
{schema.allOf.map((p, i) => <JSONSchemaFields schema={p} key={i} />)}
47+
</TableCell>
48+
</TableRow>
49+
);
50+
}
51+
if (schema.oneOf) {
52+
return (
53+
<TableRow>
54+
<TableCell colSpan={1} style={styles.cellWidth}>
55+
{schema.title || name}
56+
</TableCell>
57+
<TableCell colSpan={1} style={styles.cellWidth}>
58+
<Typography variant="body1" color="primary">one of</Typography>
59+
</TableCell>
60+
<TableCell colSpan={5}>
61+
{schema.oneOf.map((p, i) => <JSONSchemaFields schema={p} key={i} />)}
62+
</TableCell>
63+
</TableRow>
64+
);
65+
}
66+
if (schema.items instanceof Array) {
67+
return (
68+
<TableRow>
69+
<TableCell colSpan={1} style={styles.cellWidth}>
70+
{schema.title || name}
71+
</TableCell>
72+
<TableCell colSpan={1} style={styles.cellWidth}>
73+
<Typography variant="body1" color="primary">array of</Typography>
74+
</TableCell>
75+
<TableCell colSpan={5}>
76+
{schema.items.map((p, i) => <JSONSchemaFields schema={p} key={i} />)}
77+
</TableCell>
78+
</TableRow>
79+
);
80+
}
81+
if (schema.items) {
82+
return (
83+
<TableRow>
84+
<TableCell colSpan={1} style={styles.cellWidth}>
85+
{schema.title || name}
86+
</TableCell>
87+
<TableCell colSpan={1} style={styles.cellWidth}>
88+
<Typography variant="body1" color="primary">array of</Typography>
89+
</TableCell>
90+
<TableCell colSpan={5}>
91+
<JSONSchemaFields schema={schema.items} />
92+
</TableCell>
93+
</TableRow>
94+
);
95+
}
96+
97+
if (schema.properties) {
98+
return (
99+
<TableRow>
100+
<TableCell colSpan={1} style={styles.cellWidth}>
101+
{schema.title || name}
102+
</TableCell>
103+
<TableCell colSpan={1} style={styles.cellWidth}>
104+
<Typography variant="body1" color="primary">object</Typography>
105+
</TableCell>
106+
<TableCell colSpan={5}>
107+
{schema.properties && Object.entries(schema.properties).map(([n, prop]: [string, JSONSchema4], i: number) => {
108+
return (
109+
<JSONSchemaFields
110+
key={n}
111+
schema={prop}
112+
name={n}
113+
hideHeader={i !== 0}
114+
required={schema.required && schema.required.includes(n)}
115+
/>
116+
);
117+
})}
118+
</TableCell>
119+
</TableRow>
120+
);
121+
}
122+
123+
const colorMap: {[k: string]: string} = {
124+
any: grey[500],
125+
array: blue[300],
126+
boolean: blue[500],
127+
integer: purple[800],
128+
null: yellow[900],
129+
number: purple[500],
130+
string: green[500],
131+
undefined: grey[500],
132+
};
133+
return (
134+
<TableRow key={schema.title}>
135+
<TableCell component="th" scope="row" style={styles.cellWidth}>
136+
{schema.title || name}
137+
</TableCell>
138+
<TableCell style={{
139+
...styles.cellWidth,
140+
color: colorMap[schema.type as any],
141+
}}>{schema.type}</TableCell>
142+
<TableCell style={styles.cellWidth}>{schema.pattern}</TableCell>
143+
<TableCell style={styles.cellWidth}>{required ? "true" : "false"}</TableCell>
144+
<TableCell style={styles.cellWidth}>{schema.description}</TableCell>
145+
</TableRow>
146+
);
147+
};
148+
149+
export default SchemaRenderer;

0 commit comments

Comments
 (0)