Skip to content

Commit 783c897

Browse files
add support for toJSON() js objects
1 parent 0449de7 commit 783c897

File tree

8 files changed

+332
-251
lines changed

8 files changed

+332
-251
lines changed

.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
env:
22
node: true
3+
mocha: true
34

45
rules:
56
# Possible Errors
@@ -45,7 +46,7 @@ rules:
4546
## require parens for Constructor
4647
new-parens: 2
4748
## max 80 length
48-
max-len: [2, 80, 2]
49+
max-len: [2, 120, 2]
4950
## max 2 consecutive empty lines
5051
no-multiple-empty-lines: [2, {max: 2}]
5152
## require newline at end of files

README.md

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ $ npm install json-merge-patch --save
2626

2727
## Usage
2828

29-
Applying patches:
29+
### Applying patches:
3030
```js
3131
var source = {
3232
"title": "Goodbye!",
@@ -53,7 +53,7 @@ var target = jsonmergepatch.apply(source, patch);
5353
// }
5454
```
5555

56-
Generating patches:
56+
### Generating patches:
5757
```js
5858
var source = {
5959
"title": "Goodbye!",
@@ -72,6 +72,41 @@ var patch = jsonmergepatch.generate(source, target);
7272
// }
7373
```
7474

75+
76+
### Usage with Javascript objects
77+
78+
This library is primarily designed to work with JSON.
79+
Nonetheless, it is possible to use Javascript objects if the method `toJSON()` is implemented, the library will then serialize your object using it.
80+
```js
81+
var patch = jsonmergepatch.generate(
82+
{
83+
"title": "Goodbye!"
84+
},
85+
{
86+
toJSON: () {
87+
return {
88+
"title": "I am serialized"
89+
}
90+
},
91+
}
92+
);
93+
// patch = {
94+
// "title": "I am serialized",
95+
// }
96+
```
97+
98+
```js
99+
var patch = jsonmergepatch.generate(
100+
{},
101+
{
102+
date: new Date("2020-05-09T00:00:00.000")
103+
}
104+
);
105+
// patch = {
106+
// date: "2020-05-09T00:00:00.000"
107+
// }
108+
```
109+
75110
## API
76111

77112
#### jsonmergepatch.apply (`obj` Object, `patch` Object) : Object
@@ -87,10 +122,11 @@ Generates a `patch` Object from source and target Object.
87122

88123
Generates a `patch` Object by merging patch1 and patch2.
89124

125+
90126
## Running tests
91127

92128
```sh
93-
make test
129+
npm test
94130
```
95131

96132
# License

lib/apply.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
'use strict';
22

3+
var serialize = require('./utils').serialize;
4+
35
module.exports = function apply(target, patch) {
6+
patch = serialize(patch);
47
if (patch === null || typeof patch !== 'object' || Array.isArray(patch)) {
58
return patch;
69
}
10+
11+
target = serialize(target);
712
if (target === null || typeof target !== 'object' || Array.isArray(target)) {
813
target = {};
914
}

lib/generate.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
var equal = require('deep-equal');
4+
var serialize = require('./utils').serialize;
45

56
function arrayEquals(before, after) {
67
if (before.length !== after.length) {
@@ -15,6 +16,9 @@ function arrayEquals(before, after) {
1516
}
1617

1718
module.exports = function generate(before, after) {
19+
before = serialize(before);
20+
after = serialize(after);
21+
1822
if (before === null || after === null ||
1923
typeof before !== 'object' || typeof after !== 'object' ||
2024
Array.isArray(before) !== Array.isArray(after)) {
@@ -40,7 +44,7 @@ module.exports = function generate(before, after) {
4044
key = afterKeys[i];
4145
if (beforeKeys.indexOf(key) === -1) {
4246
newKeys[key] = true;
43-
patch[key] = after[key];
47+
patch[key] = serialize(after[key]);
4448
}
4549
}
4650

@@ -58,7 +62,7 @@ module.exports = function generate(before, after) {
5862
patch[key] = subPatch;
5963
}
6064
} else if (before[key] !== after[key]) {
61-
patch[key] = after[key];
65+
patch[key] = serialize(after[key]);
6266
}
6367
}
6468
}

lib/utils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
3+
module.exports.serialize = function(value) {
4+
return (value && typeof value.toJSON === 'function') ? value.toJSON() : value;
5+
};

test/lib/apply.js

Lines changed: 75 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -5,108 +5,115 @@ var assert = require('chai').assert;
55
var apply = require('../../lib/apply');
66

77
describe('apply', function() {
8-
it('should replace an attribute', function() {
9-
assert.deepEqual(
10-
apply({a: 'b'}, {a: 'c'}),
8+
it('should replace an attribute', function() {
9+
assert.deepEqual(
10+
apply({a: 'b'}, {a: 'c'}),
1111
{a: 'c'}
1212
);
13-
});
13+
});
1414

15-
it('should add an attribute', function() {
16-
assert.deepEqual(
17-
apply({a: 'b'}, {b: 'c'}),
15+
it('should add an attribute', function() {
16+
assert.deepEqual(
17+
apply({a: 'b'}, {b: 'c'}),
1818
{a: 'b', b: 'c'}
1919
);
20-
});
20+
});
2121

22-
it('should delete attribute', function() {
23-
assert.deepEqual(
24-
apply({a: 'b'}, {a: null}),
22+
it('should delete attribute', function() {
23+
assert.deepEqual(
24+
apply({a: 'b'}, {a: null}),
2525
{}
2626
);
27-
});
27+
});
2828

29-
it('should delete attribute without affecting others', function() {
30-
assert.deepEqual(
31-
apply({a: 'b', b: 'c'}, {a: null}),
29+
it('should delete attribute without affecting others', function() {
30+
assert.deepEqual(
31+
apply({a: 'b', b: 'c'}, {a: null}),
3232
{b: 'c'}
3333
);
34-
});
34+
});
3535

36-
it('should replace array with a string', function() {
37-
assert.deepEqual(
38-
apply({a: ['b']}, {a: 'c'}),
36+
it('should replace array with a string', function() {
37+
assert.deepEqual(
38+
apply({a: ['b']}, {a: 'c'}),
3939
{a: 'c'}
4040
);
41-
});
41+
});
4242

43-
it('should replace an string with an array', function() {
44-
assert.deepEqual(
45-
apply({a: 'c'}, {a: ['b']}),
43+
it('should replace an string with an array', function() {
44+
assert.deepEqual(
45+
apply({a: 'c'}, {a: ['b']}),
4646
{a: ['b']}
4747
);
48-
});
48+
});
4949

50-
it('should apply recursively', function() {
51-
assert.deepEqual(
52-
apply({a: {b: 'c'}}, {a: {b: 'd', c: null}}),
50+
it('should apply recursively', function() {
51+
assert.deepEqual(
52+
apply({a: {b: 'c'}}, {a: {b: 'd', c: null}}),
5353
{a: {b: 'd'}}
5454
);
55-
});
55+
});
5656

57-
it('should replace an object array with a number array', function() {
58-
assert.deepEqual(
59-
apply({a: [{b: 'c'}]}, {a: [1]}),
57+
it('should replace an object array with a number array', function() {
58+
assert.deepEqual(
59+
apply({a: [{b: 'c'}]}, {a: [1]}),
6060
{a: [1]}
6161
);
62-
});
62+
});
6363

64-
it('should replace an array', function() {
65-
assert.deepEqual(
66-
apply(['a', 'b'], ['c', 'd']),
67-
['c', 'd']
64+
it('should replace an array', function() {
65+
assert.deepEqual(
66+
apply(['a', 'b'], ['c', 'd']),
67+
['c', 'd']
6868
);
69-
});
69+
});
7070

71-
it('should replace an object with an array', function() {
72-
assert.deepEqual(
73-
apply({a: 'b'}, ['c']),
74-
['c']
71+
it('should replace an object with an array', function() {
72+
assert.deepEqual(
73+
apply({a: 'b'}, ['c']),
74+
['c']
7575
);
76-
});
76+
});
7777

78-
it('should replace an object with null', function() {
79-
assert.deepEqual(
80-
apply({a: 'foo'}, null),
81-
null
78+
it('should replace an object with null', function() {
79+
assert.deepEqual(
80+
apply({a: 'foo'}, null),
81+
null
8282
);
83-
});
83+
});
8484

85-
it('should replace an object with a string', function() {
86-
assert.deepEqual(
87-
apply({a: 'foo'}, 'bar'),
88-
'bar'
85+
it('should replace with an object implementing toJSON() method', function() {
86+
assert.deepEqual(
87+
apply({a: 'foo'}, {a: new Date('2020-05-09T00:00:00.000Z')}),
88+
{a: '2020-05-09T00:00:00.000Z'}
8989
);
90-
});
90+
});
9191

92-
it('should not change null attributes', function() {
93-
assert.deepEqual(
94-
apply({e: null}, {a: 1}),
95-
{e: null, a: 1}
92+
it('should replace an object with a string', function() {
93+
assert.deepEqual(
94+
apply({a: 'foo'}, 'bar'),
95+
'bar'
9696
);
97-
});
97+
});
9898

99-
it('should not set an attribute to null', function() {
100-
assert.deepEqual(
101-
apply([1, 2], {a: 'b', c: null}),
102-
{a: 'b'}
99+
it('should not change null attributes', function() {
100+
assert.deepEqual(
101+
apply({e: null}, {a: 1}),
102+
{e: null, a: 1}
103103
);
104-
});
104+
});
105105

106-
it('should not set an attribute to null in a sub object', function() {
107-
assert.deepEqual(
108-
apply({}, {a: {bb: {ccc: null}}}),
109-
{a: {bb: {}}}
110-
);
111-
});
106+
it('should not set an attribute to null', function() {
107+
assert.deepEqual(
108+
apply([1, 2], {a: 'b', c: null}),
109+
{a: 'b'}
110+
);
111+
});
112+
113+
it('should not set an attribute to null in a sub object', function() {
114+
assert.deepEqual(
115+
apply({}, {a: {bb: {ccc: null}}}),
116+
{a: {bb: {}}}
117+
);
118+
});
112119
});

0 commit comments

Comments
 (0)