ArnaudBuchholz/gpf-js

View on GitHub
src/compatibility/json/stringify.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * @file JSON.stringify polyfill
 * @since 0.1.5
 */
/*#ifndef(UMD)*/
"use strict";
/*global _gpfArrayForEach*/ // Almost like [].forEach (undefined are also enumerated)
/*global _gpfEmptyFunc*/ // An empty function
/*global _gpfIsArray*/ // Return true if the parameter is an array
/*global _gpfObjectForEach*/ // Similar to [].forEach but for objects
/*global _gpfStringEscapeForJavascript*/ // String escape for JavaScript
/*exported _gpfJsonStringifyPolyfill*/ // JSON.stringify polyfill
/*#endif*/

var _gpfJsonStringifyMapping;

function _gpfJsonStringifyGeneric (object) {
    return object.toString();
}

function _gpfJsonStringifyFormat (values, space) {
    if (space) {
        return "\n" + space + values.join(",\n" + space) + "\n";
    }
    return values.join(",");
}

function _gpfJsonStringifyArray (array, replacer, space) {
    var values = [];
    _gpfArrayForEach(array, function (value, index) {
        var replacedValue = replacer(index.toString(), value);
        if (undefined === replacedValue) {
            replacedValue = "null";
        } else {
            replacedValue = _gpfJsonStringifyMapping[typeof replacedValue](replacedValue, replacer, space);
        }
        values.push(replacedValue);
    });
    return "[" + _gpfJsonStringifyFormat(values, space) + "]";
}

function _gpfJsonStringifyObjectMembers (object, replacer, space) {
    var values = [],
        separator;
    if (space) {
        separator = ": ";
    } else {
        separator = ":";
    }
    _gpfObjectForEach(object, function (value, name) {
        var replacedValue = replacer(name, value);
        replacedValue = _gpfJsonStringifyMapping[typeof replacedValue](value, replacer, space);
        if (undefined === replacedValue) {
            return;
        }
        values.push(_gpfStringEscapeForJavascript(name) + separator + replacedValue);
    });
    return "{" + _gpfJsonStringifyFormat(values, space) + "}";
}

function _gpfJsonStringifyObject (object, replacer, space) {
    if (object === null) {
        return "null";
    }
    return _gpfJsonStringifyObjectMembers(object, replacer, space);
}

_gpfJsonStringifyMapping = {
    undefined: _gpfEmptyFunc,
    "function": _gpfEmptyFunc,
    number: _gpfJsonStringifyGeneric,
    "boolean": _gpfJsonStringifyGeneric,
    string: function (object) {
        return _gpfStringEscapeForJavascript(object);
    },
    object: function (object, replacer, space) {
        if (_gpfIsArray(object)) {
            return _gpfJsonStringifyArray(object, replacer, space);
        }
        return _gpfJsonStringifyObject(object, replacer, space);
    }
};

function _gpfJsonStringifyGetReplacerFunction (replacer) {
    if (typeof replacer === "function") {
        return replacer;
    }
    return function (key, value) {
        return value;
    };
}

function _gpfJsonStringifyCheckReplacer (replacer) {
    if (_gpfIsArray(replacer)) {
        // whitelist
        return function (key, value) {
            if (replacer.includes(key)) {
                return value;
            }
        };
    }
    return _gpfJsonStringifyGetReplacerFunction(replacer);
}

var _GPF_COMPATIBILITY_JSON_STRINGIFY_MAX_SPACE = 10;

function _gpfJsonStringifyCheckSpaceValue (space) {
    if (typeof space === "number") {
        return "".padEnd(Math.min(space, _GPF_COMPATIBILITY_JSON_STRINGIFY_MAX_SPACE), " ");
    }
    return space || "";
}

/**
 * JSON.stringify polyfill
 *
 * @param {*} value The value to convert to a JSON string
 * @param {Function|Array} [replacer] A function that alters the behavior of the stringification process, or an array of
 * String and Number objects that serve as a whitelist for selecting/filtering the properties of the value object to be
 * included in the JSON string
 * @param {String|Number} [space] A String or Number object that's used to insert white space into the output JSON
 * string for readability purposes. If this is a Number, it indicates the number of space characters to use as white
 * space; this number is capped at 10 (if it is greater, the value is just 10).
 * @return {String} JSON representation of the value
 * @since 0.1.5
 */
function _gpfJsonStringifyPolyfill (value, replacer, space) {
    return _gpfJsonStringifyMapping[typeof value](value, _gpfJsonStringifyCheckReplacer(replacer),
        _gpfJsonStringifyCheckSpaceValue(space));
}

/*#ifndef(UMD)*/

gpf.internals._gpfJsonStringifyPolyfill = _gpfJsonStringifyPolyfill;

/*#endif*/