Skip to content

Commit

Permalink
change the behavior in case of undefined value
Browse files Browse the repository at this point in the history
this is a fix for issues #105, #90, #60, #32 and a part of #76 that describes a problem with undefined
all tests pass after this commit
  • Loading branch information
warpech committed Jun 3, 2016
1 parent 415a168 commit 1783263
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 17 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,11 @@ As `undefined` is not a valid value for any JSON node, it's also not valid value
However, to play nicer with natural JavaScipt objects `jsonpatch` can be applied to an object that contains `undefined`, in such case we will treat it as JS does. `.apply` will handle JSON Patches with `value: undefined` as any other falsy value. `.generate`, `.compare`, `.observe` methods will also produce JSON Patches with `undefined`s, but only for (non valid) JSON documents that contains it.


## :no_entry_sign: `undefined`s (JS to JSON projection)
## `undefined`s (JS to JSON projection)

~~As `undefined` is not a valid value for any JSON node, it's also not valid value o JSON Patch operation object value property. Therefore `jsonpatch` will not generate JSON Patches that sets anything to `undefined`.~~
As `undefined` type does not exist in JSON, it's also not a valid value of JSON Patch operation. Therefore `jsonpatch` will not generate JSON Patches that sets anything to `undefined`.

~~However, to play nicer with natural JavaScipt objects `jsonpatch` can be applied to an object that contains `undefined`, in such case we will use it as native `JSON.stringify` - we will treat them as non-existing nodes, and map to `null` for array elements.~~
Whenever a value is set to `undefined` in JS, JSON-Patch methods `generate` and `compare` will treat it similarly to how JavaScript method `JSON.stringify` treats them. See the test suite (in the `test/` subdirectory) or the [ECMAScript spec](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-json.stringify) for details.

## Changelog

Expand Down
16 changes: 9 additions & 7 deletions src/json-patch-duplex.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,13 @@ var jsonpatch;
}
jsonpatch.unobserve = unobserve;
function deepClone(obj) {
if (typeof obj === "object") {
return JSON.parse(JSON.stringify(obj)); //Faster than ES5 clone - http://jsperf.com/deep-cloning-of-objects/5
}
else {
return obj; //no need to clone primitives
switch (typeof obj) {
case "object":
return JSON.parse(JSON.stringify(obj)); //Faster than ES5 clone - http://jsperf.com/deep-cloning-of-objects/5
case "undefined":
return null; //this is how JSON.stringify behaves for array items
default:
return obj; //no need to clone primitives
}
}
function observe(obj, callback) {
Expand Down Expand Up @@ -359,7 +361,7 @@ var jsonpatch;
for (var t = oldKeys.length - 1; t >= 0; t--) {
var key = oldKeys[t];
var oldVal = mirror[key];
if (obj.hasOwnProperty(key)) {
if (obj.hasOwnProperty(key) && !(_isArray(obj) === false && obj[key] === undefined)) {
var newVal = obj[key];
if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null) {
_generate(oldVal, newVal, patches, path + "/" + escapePathComponent(key));
Expand All @@ -381,7 +383,7 @@ var jsonpatch;
}
for (var t = 0; t < newKeys.length; t++) {
var key = newKeys[t];
if (!mirror.hasOwnProperty(key)) {
if (!mirror.hasOwnProperty(key) && obj[key] !== undefined) {
patches.push({ op: "add", path: path + "/" + escapePathComponent(key), value: deepClone(obj[key]) });
}
}
Expand Down
18 changes: 11 additions & 7 deletions src/json-patch-duplex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,15 @@ module jsonpatch {
}

function deepClone(obj:any) {
if (typeof obj === "object") {
return JSON.parse(JSON.stringify(obj)); //Faster than ES5 clone - http://jsperf.com/deep-cloning-of-objects/5
}
else {
return obj; //no need to clone primitives
switch (typeof obj) {
case "object":
return JSON.parse(JSON.stringify(obj)); //Faster than ES5 clone - http://jsperf.com/deep-cloning-of-objects/5

case "undefined":
return null; //this is how JSON.stringify behaves for array items

default:
return obj; //no need to clone primitives
}
}

Expand Down Expand Up @@ -400,7 +404,7 @@ module jsonpatch {
for (var t = oldKeys.length - 1; t >= 0; t--) {
var key = oldKeys[t];
var oldVal = mirror[key];
if (obj.hasOwnProperty(key)) {
if (obj.hasOwnProperty(key) && !(_isArray(obj) === false && obj[key] === undefined)) {
var newVal = obj[key];
if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null) {
_generate(oldVal, newVal, patches, path + "/" + escapePathComponent(key));
Expand All @@ -424,7 +428,7 @@ module jsonpatch {

for (var t = 0; t < newKeys.length; t++) {
var key = newKeys[t];
if (!mirror.hasOwnProperty(key)) {
if (!mirror.hasOwnProperty(key) && obj[key] !== undefined) {
patches.push({op: "add", path: path + "/" + escapePathComponent(key), value: deepClone(obj[key])});
}
}
Expand Down

0 comments on commit 1783263

Please sign in to comment.