src/query/stableStringify.js
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule stableStringify
* @flow
*/
'use strict';
function isObject(value: mixed) {
return (
value !== null &&
Object.prototype.toString.call(value) === '[object Object]'
);
}
/**
* Simple recursive stringifier that handles basic objects (does not handle
* corner cases such as circular references) and produces a JSON-like
* serialization suitable for use as a cache key or other similar internal
* book-keeping detail.
*
* Sample input:
*
* var object = {
* top2: {
* middle: {
* inner: [1, 'foo', ['bar', 2]],
* other: false,
* },
* },
* top1: [
* {first: true},
* {first: false},
* 'random',
* ],
* misc: true,
* extra: null,
* };
*
* Sample output (some whitespace added for clarity):
*
* {
* extra:null,
* misc:true,
* top1:[0:{first:true},1:{first:false},2:"random"],
* top2:{middle:{inner:[0:1,1:"foo",2:[0:"bar",1:2]],other:false}}
* }
*/
function stableStringify(input: any): string {
const inputIsArray = Array.isArray(input);
const inputIsObject = isObject(input);
if (inputIsArray || inputIsObject) {
const keys = Object.keys(input);
if (keys.length) {
const result = [];
keys.sort();
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
let value = input[key];
if (isObject(value) || Array.isArray(value)) {
value = stableStringify(value);
} else {
value = JSON.stringify(value);
}
result.push(key + ':' + value);
}
if (inputIsArray) {
return '[' + result.join(',') + ']';
} else {
return '{' + result.join(',') + '}';
}
}
}
return JSON.stringify(input);
}
module.exports = stableStringify;