EN
JavaScript - custom compare JSONs function
8 points
In this article, we're going to have a look at how to write own function to compare JSONs. Approach used in this article encloses each entity with object that keeps previous and current values with types and kind of change.
Example result:
xxxxxxxxxx
1
{
2
"name": "propertyName",
3
"status": "changed",
4
"oldType": "simple",
5
"newType": "simple",
6
"oldValue": "Some old value",
7
"newValue": "Some new value"
8
}
Where:
status
can be one of:unchanged
,updated
,created
ordeleted
,- old and new type:
array
,object
,simple
ornull
, - old and new value: simple type object, array with enclosed entities that describe nested objects or
null
.
Note: read this article to see json difference visualization.
Run below example to see details.
This section presents simple logic that returns object with difference information.
xxxxxxxxxx
1
function getType(object) {
2
return Object.prototype.toString.call(object);
3
}
4
5
function getDescription(type) {
6
if (type == '[object Array]') {
7
return 'array';
8
}
9
if (type == '[object Object]') {
10
return 'object';
11
}
12
return 'simple';
13
}
14
15
function createOldItem(name, status, type, value) {
16
return {
17
name: name || null,
18
status: status,
19
oldType: getDescription(type),
20
newType: null,
21
oldValue: value,
22
newValue: null,
23
};
24
}
25
26
function createNewItem(name, status, type, value) {
27
return {
28
name: name || null,
29
status: status,
30
oldType: null,
31
newType: getDescription(type),
32
oldValue: null,
33
newValue: value,
34
};
35
}
36
37
function createDeletedItem(key, type, value) {
38
return createOldItem(key, 'deleted', type, value);
39
}
40
41
function createCreatedItem(key, type, value) {
42
return createNewItem(key, 'created', type, value);
43
}
44
45
function coverContent(entity, createItem) {
46
var items = [ ];
47
for (const key in entity) {
48
if (entity.hasOwnProperty(key)) {
49
items.push(coverEntity(key, entity[key], createItem));
50
}
51
}
52
return items;
53
}
54
55
function coverEntity(name, entity, createItem) {
56
var type = getType(entity);
57
if (type === '[object Array]' || type === '[object Object]') {
58
var content = coverContent(entity, createItem);
59
return createItem(name, type, content);
60
} else {
61
return createItem(name, type, entity);
62
}
63
}
64
65
function compareContent(a, b) {
66
var items = [ ];
67
for (const key in a) {
68
if (a.hasOwnProperty(key)) {
69
if (b.hasOwnProperty(key)) {
70
items.push(compareEntries(a[key], b[key], key));
71
} else {
72
items.push(coverEntity(key, a[key], createDeletedItem));
73
}
74
}
75
}
76
for (const key in b) {
77
if (b.hasOwnProperty(key)) {
78
if(a.hasOwnProperty(key)){
79
continue;
80
}
81
items.push(coverEntity(key, b[key], createCreatedItem));
82
}
83
}
84
return items;
85
}
86
87
function compareEntries(a, b, name) {
88
var oldType = getType(a);
89
var newType = getType(b);
90
if (a === b) {
91
return createOldItem(name, 'unchanged', oldType, a);
92
}
93
if (oldType == newType) {
94
// both have array or object type:
95
if (oldType === '[object Array]' || oldType === '[object Object]') {
96
var oldValue = compareContent(a, b);
97
return createOldItem(name, 'unchanged', oldType, oldValue);
98
}
99
// both have simple type: boolean, number, string, etc.:
100
var description = getDescription(oldType);
101
return {
102
name: name || null,
103
status: 'updated',
104
oldType: description,
105
newType: description,
106
oldValue: a,
107
newValue: b,
108
};
109
} else {
110
// both have different types:
111
var oldDescription = getDescription(oldType);
112
var newDescription = getDescription(newType);
113
return {
114
name: name || null,
115
status: 'updated',
116
oldType: oldDescription,
117
newType: newDescription,
118
oldValue: (oldDescription == 'simple' ? a : coverContent(a, createDeletedItem)),
119
newValue: (newDescription == 'simple' ? b : coverContent(b, createCreatedItem)),
120
};
121
}
122
}
123
124
function compareJsons(a, b) {
125
var aEntity = JSON.parse(a);
126
var bEntity = JSON.parse(b);
127
return compareEntries(aEntity, bEntity);
128
}
129
130
131
// Usage example:
132
133
var json1 = '{"name":"John","items":[1,2,"3",{"name":"Item","z":[4]},5]}';
134
var json2 = '{"name":"John","items":["1",2,3,{"name":"Item 2","x":3}]}';
135
136
var difference = compareJsons(json1, json2);
137
138
console.log(JSON.stringify(difference, null, 4));