EN
JavaScript - simple own json schema
9 points
In this short article we would like to show how in JavaScript write simple logic to manage simple JSON schema.
The article contains three parts:
- example schmeas,
- simple logic that let us to fill empty properies in some object to unify object with schema,
- simple logic that let us to validate object according to schema.
Below array contains simple usage cases only, but it is verry easy to understand the template. The main idea of the schema is to use type property to describe JSON part type
: boolean
, number
, string
, array
or object
.
Example schemna | Example JSON |
xxxxxxxxxx 1 const schema = { 2 type: 'object', 3 properties: [ 4 {name: 'name', type: 'string'}, 5 {name: 'age', type: 'number'}, 6 ] 7 } |
xxxxxxxxxx 1 {name: 'John', age: 26} 2 3 4 5 6 7 |
Example schemna | Example JSON |
xxxxxxxxxx 1 const schema = { 2 type: 'array', 3 item: { 4 // without name because array items don't have names 5 type: 'string' 6 // or: 7 // type: 'number' 8 // or: 9 // type: 'boolean' 10 // or: 11 // type: 'object', properties: [] 12 // or: 13 // type: 'array', item: {} 14 } 15 } |
xxxxxxxxxx 1 ['a', 'b', 'c'] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Example schemna | Example JSON |
xxxxxxxxxx 1 const schema = { 2 type: 'object', 3 properties: [ 4 {name: 'name', type: 'string'}, 5 {name: 'age', type: 'number'}, 6 { 7 name: 'address', 8 type: 'object', // type: 'object' requires to provide object properties 9 properties: [ 10 {name: 'country', type: 'string'}, 11 {name: 'city', type: 'string'}, 12 {name: 'postcode', type: 'string'}, 13 {name: 'street', type: 'string'}, 14 {name: 'number', type: 'string'} 15 ] 16 } 17 ] 18 } |
xxxxxxxxxx 1 { 2 name: 'John', 3 age: 26, 4 address: { 5 country: 'UK', 6 city: 'London', 7 postcode: '000 000', 8 street: null, 9 number: null 10 } 11 } 12 13 14 15 16 17 18 |
Example schemna | Example JSON |
xxxxxxxxxx 1 const schema = { 2 type: 'object', 3 properties: [ 4 {name: 'name', type: 'string'}, 5 {name: 'age', type: 'number'}, 6 { 7 name: 'tasks', 8 type: 'array', // type: 'array' requires to provide JSON array item definition 9 item: { 10 // without name because array items don't have names 11 type: 'string' 12 // or: 13 // type: 'number' 14 // or: 15 // type: 'boolean' 16 // or: 17 // type: 'object', properties: [] 18 // or: 19 // type: 'array', item: {} 20 } 21 } 22 ] 23 } |
xxxxxxxxxx 1 { 2 name: 'John', 3 age: 26, 4 tasks: ['a', 'b', 'c'] 5 } 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
In this section we would like to show how to write simple logic that let us to fill a object with null properties if some fields defined in JSON Schema were not defined in the object that we want to unify.
xxxxxxxxxx
1
const createValue = (schema, initialValue) => {
2
if (schema.type === 'object') {
3
return createObject(schema.properties, initialValue);
4
}
5
if (schema.type === 'array') {
6
return createArray(schema.item, initialValue);
7
}
8
return initialValue ?? null;
9
};
10
11
const createObject = (schema, initialObject) => {
12
const data = {};
13
if (schema) {
14
for (const entry of schema) {
15
data[entry.name] = createValue(entry, initialObject?.[entry.name]);
16
}
17
}
18
return data;
19
};
20
21
const createArray = (schema, initialArray) => {
22
const data = [];
23
if (initialArray) {
24
for (let i = 0; i < initialArray.length; ++i) {
25
data.push(createValue(schema, initialArray[i]));
26
}
27
}
28
return data;
29
};
30
31
const createData = (schema, initialData) => {
32
return createValue(schema, initialData);
33
};
34
35
// Usage example:
36
37
const schema = {
38
type: 'object',
39
properties: [
40
{name: 'name', type: 'string'},
41
{name: 'age', type: 'number'},
42
{
43
name: 'tasks',
44
type: 'array',
45
item: {
46
type: 'string'
47
}
48
},
49
{
50
name: 'address',
51
type: 'object',
52
properties: [
53
{name: 'country', type: 'string'},
54
{name: 'city', type: 'string'},
55
{name: 'postcode', type: 'string'},
56
{name: 'street', type: 'string'},
57
{name: 'number', type: 'string'}
58
]
59
}
60
]
61
};
62
63
const data1 = {}; // this object will be filled with missing poprerties
64
const data2 = {
65
name: 'John',
66
// age property will be added
67
tasks: ['do shopping', 'find job', 'go to gym'],
68
address: {
69
country: 'UK',
70
city: 'London',
71
// postcode property will be added
72
// street property will be added
73
// number property will be added
74
}
75
};
76
77
console.log(JSON.stringify(createData(schema, data1), null, 5));
78
console.log(JSON.stringify(createData(schema, data2), null, 5));
This section contains example JSON Schema validation logic.
xxxxxxxxxx
1
const validateValue = (schema, value) => {
2
if (schema.type === 'object') {
3
return validateObject(schema.properties, value);
4
}
5
if (schema.type === 'array') {
6
return validateArray(schema.item, value);
7
}
8
return (schema.type === typeof value); // e.g. boolean, string, number
9
};
10
11
const validateObject = (schema, object) => {
12
if (schema) {
13
if (object === undefined || object === null) {
14
return false;
15
}
16
for (const entry of schema) {
17
if (!validateValue(entry, object[entry.name])) {
18
return false;
19
}
20
}
21
}
22
return true;
23
};
24
25
const validateArray = (schema, array) => {
26
if (array) {
27
if (schema === undefined || schema == null) {
28
return false;
29
}
30
for (let i = 0; i < array.length; ++i) {
31
if (!validateValue(schema, array[i])) {
32
return false;
33
}
34
}
35
}
36
return true;
37
};
38
39
const validateData = (schema, data) => {
40
return validateValue(schema, data);
41
};
42
43
// Usage example:
44
45
const schema = {
46
type: 'object',
47
properties: [
48
{name: 'name', type: 'string'},
49
{name: 'age', type: 'number'},
50
{
51
name: 'tasks',
52
type: 'array',
53
item: {
54
type: 'string'
55
}
56
},
57
{
58
name: 'address',
59
type: 'object',
60
properties: [
61
{name: 'country', type: 'string'},
62
{name: 'city', type: 'string'},
63
{name: 'postcode', type: 'string'},
64
{name: 'street', type: 'string'},
65
{name: 'number', type: 'string'}
66
]
67
}
68
]
69
};
70
71
const data1 = {}; // not valid schema - all properties undefined
72
73
const data2 = { // not valid schema - some properties undefined
74
name: 'John',
75
// age property undefined
76
tasks: ['do shopping', 'find job', 'go to gym'],
77
address: {
78
country: 'UK',
79
city: 'London',
80
// postcode property undefined
81
// street property undefined
82
// number property undefined
83
}
84
};
85
86
const data3 = { // valid schema
87
name: 'John',
88
age: 26,
89
tasks: ['do shopping', 'find job', 'go to gym'],
90
address: {
91
country: 'UK',
92
city: 'London',
93
postcode: 'SW1A 0AA',
94
street: 'Great George St.',
95
number: '44a'
96
}
97
};
98
99
console.log(validateData(schema, data1)); // false
100
console.log(validateData(schema, data2)); // false
101
console.log(validateData(schema, data3)); // true