PHP's json_decode in JavaScript

How to use

You you can install via yarn add locutus and require this function via const json_decode = require('locutus/php/json/json_decode').

It is important to use a bundler that supports tree-shaking so that you only ship the functions that you actually use to your browser, instead of all of Locutus, which is massive. Examples are: Parcel, webpack, or rollup.js. For server-side use this is typically less of a concern.

Examples

Please note that these examples are distilled from test cases that automatically verify our functions still work correctly. This could explain some quirky ones.

#codeexpected result
1json_decode('[ 1 ]')[1]

Notes

  • If node or the browser does not offer JSON.parse, this function falls backslash to its own implementation using eval, and hence should be considered unsafe

Here’s what our current JavaScript equivalent to PHP's json_decode looks like.

module.exports = function json_decode(strJson) {
// discuss at: https://phpjs.org/functions/json_decode/
// original by: Public Domain (https://www.json.org/json2.js)
// reimplemented by: Kevin van Zonneveld (https://kevin.vanzonneveld.net)
// improved by: T.J. Leahy
// improved by: Michael White
// note 1: If node or the browser does not offer JSON.parse,
// note 1: this function falls backslash
// note 1: to its own implementation using eval, and hence should be considered unsafe
// example 1: json_decode('[ 1 ]')
// returns 1: [1]

/*
https://www.JSON.org/json2.js
2008-11-19
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See https://www.JSON.org/js.html
*/

const $global = typeof window !== 'undefined' ? window : global
$global.$locutus = $global.$locutus || {}
const $locutus = $global.$locutus
$locutus.php = $locutus.php || {}

const json = $global.JSON
if (typeof json === 'object' && typeof json.parse === 'function') {
try {
return json.parse(strJson)
} catch (err) {
if (!(err instanceof SyntaxError)) {
throw new Error('Unexpected error type in json_decode()')
}

// usable by json_last_error()
$locutus.php.last_error_json = 4
return null
}
}

const chars = [
'\u0000',
'\u00ad',
'\u0600-\u0604',
'\u070f',
'\u17b4',
'\u17b5',
'\u200c-\u200f',
'\u2028-\u202f',
'\u2060-\u206f',
'\ufeff',
'\ufff0-\uffff',
].join('')
const cx = new RegExp('[' + chars + ']', 'g')
let j
let text = strJson

// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
cx.lastIndex = 0
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)
})
}

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

const m = /^[\],:{}\s]*$/.test(
text
.replace(/\\(?:["\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''),
)

if (m) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')') // eslint-disable-line no-eval
return j
}

// usable by json_last_error()
$locutus.php.last_error_json = 4
return null
}

A community effort

Not unlike Wikipedia, Locutus is an ongoing community effort. Our philosophy follows The McDonald’s Theory. This means that we assimilate first iterations with imperfections, hoping for others to take issue with-and improve them. This unorthodox approach has worked very well to foster fun and fruitful collaboration, but please be reminded to use our creations at your own risk. THE SOFTWARE IS PROVIDED "AS IS" has never been more true than for Locutus.

Now go and: [ View on GitHub | Edit on GitHub | View Raw ]


« More PHP json functions


Star