mirror of
https://github.com/donl/JSON-js.git
synced 2026-05-25 22:06:23 -06:00
replacer
This commit is contained in:
parent
a48e0c7944
commit
ff3f6415b2
1 changed files with 74 additions and 64 deletions
138
cycle.js
138
cycle.js
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
cycle.js
|
||||
2015-02-25
|
||||
2016-05-01
|
||||
|
||||
Public Domain.
|
||||
|
||||
|
|
@ -15,60 +15,75 @@
|
|||
|
||||
/*jslint eval, for */
|
||||
|
||||
/*property
|
||||
$ref, apply, call, decycle, hasOwnProperty, length, prototype, push,
|
||||
retrocycle, stringify, test, toString
|
||||
/*property
|
||||
$ref, decycle, forEach, isArray, keys, length, push, retrocycle, stringify,
|
||||
test
|
||||
*/
|
||||
|
||||
if (typeof JSON.decycle !== 'function') {
|
||||
JSON.decycle = function decycle(object) {
|
||||
'use strict';
|
||||
if (typeof JSON.decycle !== "function") {
|
||||
JSON.decycle = function decycle(object, replacer) {
|
||||
"use strict";
|
||||
|
||||
// Make a deep copy of an object or array, assuring that there is at most
|
||||
// one instance of each object or array in the resulting structure. The
|
||||
// duplicate references (which might be forming cycles) are replaced with
|
||||
// an object of the form
|
||||
// {$ref: PATH}
|
||||
|
||||
// {"$ref": PATH}
|
||||
|
||||
// where the PATH is a JSONPath string that locates the first occurance.
|
||||
|
||||
// So,
|
||||
|
||||
// var a = [];
|
||||
// a[0] = a;
|
||||
// return JSON.stringify(JSON.decycle(a));
|
||||
|
||||
// produces the string '[{"$ref":"$"}]'.
|
||||
|
||||
// If a replacer function is provided, then it will be called for each value.
|
||||
// A replacer function receives a value and returns a replacement value.
|
||||
|
||||
// JSONPath is used to locate the unique object. $ indicates the top level of
|
||||
// the object or array. [NUMBER] or [STRING] indicates a child member or
|
||||
// the object or array. [NUMBER] or [STRING] indicates a child element or
|
||||
// property.
|
||||
|
||||
var objects = [], // Keep a reference to each unique object or array
|
||||
paths = []; // Keep the path to each unique object or array
|
||||
var objects = []; // Keep a reference to each unique object or array
|
||||
var paths = []; // Keep the path to each unique object or array
|
||||
|
||||
return (function derez(value, path) {
|
||||
|
||||
// The derez recurses through the object, producing the deep copy.
|
||||
// The derez function recurses through the object, producing the deep copy.
|
||||
|
||||
var i, // The loop counter
|
||||
name, // Property name
|
||||
nu; // The new object or array
|
||||
var i; // The loop counter
|
||||
var nu; // The new object or array
|
||||
|
||||
// typeof null === 'object', so go on if this value is really an object but not
|
||||
// If a replacer function was provided, then call it to get a replacement value.
|
||||
|
||||
if (replacer !== undefined) {
|
||||
value = replacer(value);
|
||||
}
|
||||
|
||||
// typeof null === "object", so go on if this value is really an object but not
|
||||
// one of the weird builtin objects.
|
||||
|
||||
if (typeof value === 'object' && value !== null &&
|
||||
!(value instanceof Boolean) &&
|
||||
!(value instanceof Date) &&
|
||||
!(value instanceof Number) &&
|
||||
!(value instanceof RegExp) &&
|
||||
!(value instanceof String)) {
|
||||
if (
|
||||
typeof value === "object" && value !== null &&
|
||||
!(value instanceof Boolean) &&
|
||||
!(value instanceof Date) &&
|
||||
!(value instanceof Number) &&
|
||||
!(value instanceof RegExp) &&
|
||||
!(value instanceof String)
|
||||
) {
|
||||
|
||||
// If the value is an object or array, look to see if we have already
|
||||
// encountered it. If so, return a $ref/path object. This is a hard way,
|
||||
// encountered it. If so, return a {"$ref":PATH} object. This is a hard
|
||||
// linear search that will get slower as the number of unique objects grows.
|
||||
// Someday, this should be replaced with an ES6 WeakMap.
|
||||
|
||||
for (i = 0; i < objects.length; i += 1) {
|
||||
if (objects[i] === value) {
|
||||
return {$ref: paths[i]};
|
||||
}
|
||||
i = objects.indexOf(value);
|
||||
if (i >= 0) {
|
||||
return {$ref: paths[i]};
|
||||
}
|
||||
|
||||
// Otherwise, accumulate the unique value and its path.
|
||||
|
|
@ -78,34 +93,34 @@ if (typeof JSON.decycle !== 'function') {
|
|||
|
||||
// If it is an array, replicate the array.
|
||||
|
||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||
if (Array.isArray(value)) {
|
||||
nu = [];
|
||||
for (i = 0; i < value.length; i += 1) {
|
||||
nu[i] = derez(value[i], path + '[' + i + ']');
|
||||
}
|
||||
value.forEach(function (element, i) {
|
||||
nu[i] = derez(element, path + "[" + i + "]");
|
||||
});
|
||||
} else {
|
||||
|
||||
// If it is an object, replicate the object.
|
||||
|
||||
nu = {};
|
||||
for (name in value) {
|
||||
if (Object.prototype.hasOwnProperty.call(value, name)) {
|
||||
nu[name] = derez(value[name],
|
||||
path + '[' + JSON.stringify(name) + ']');
|
||||
}
|
||||
}
|
||||
Object.keys(value).forEach(function (name) {
|
||||
nu[name] = derez(
|
||||
value[name],
|
||||
path + "[" + JSON.stringify(name) + "]"
|
||||
);
|
||||
});
|
||||
}
|
||||
return nu;
|
||||
}
|
||||
return value;
|
||||
}(object, '$'));
|
||||
}(object, "$"));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
if (typeof JSON.retrocycle !== 'function') {
|
||||
if (typeof JSON.retrocycle !== "function") {
|
||||
JSON.retrocycle = function retrocycle($) {
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
// Restore an object that was reduced by decycle. Members whose values are
|
||||
// objects of the form
|
||||
|
|
@ -135,35 +150,30 @@ if (typeof JSON.retrocycle !== 'function') {
|
|||
// replaces the $ref object with a reference to the value that is found by
|
||||
// the path.
|
||||
|
||||
var i, item, name, path;
|
||||
|
||||
if (value && typeof value === 'object') {
|
||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||
for (i = 0; i < value.length; i += 1) {
|
||||
item = value[i];
|
||||
if (item && typeof item === 'object') {
|
||||
path = item.$ref;
|
||||
if (typeof path === 'string' && px.test(path)) {
|
||||
if (value && typeof value === "object") {
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach(function (element, i) {
|
||||
if (typeof element === "object" && element !== null) {
|
||||
var path = element.$ref;
|
||||
if (typeof path === "string" && px.test(path)) {
|
||||
value[i] = eval(path);
|
||||
} else {
|
||||
rez(element);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Object.keys(value).forEach(function (name) {
|
||||
var item = value[name];
|
||||
if (typeof item === "object" && item !== null) {
|
||||
var path = item.$ref;
|
||||
if (typeof path === "string" && px.test(path)) {
|
||||
value[name] = eval(path);
|
||||
} else {
|
||||
rez(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (name in value) {
|
||||
if (typeof value[name] === 'object') {
|
||||
item = value[name];
|
||||
if (item) {
|
||||
path = item.$ref;
|
||||
if (typeof path === 'string' && px.test(path)) {
|
||||
value[name] = eval(path);
|
||||
} else {
|
||||
rez(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}($));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue