Examples tested against actual runtime. CI re-verifies continuously. Only documented examples are tested.
How to use
Install via yarn add locutus and import:
import { json_decode } from 'locutus/php/json/json_decode'.
Or with CommonJS: const { json_decode } = require('locutus/php/json/json_decode')
Use a bundler that supports tree-shaking so you only ship the functions you actually use.
Vite,
webpack,
Rollup, and
Parcel
all handle this. For server-side use this is less of a concern.
Examples
These examples are extracted from test cases that automatically verify our functions against their native counterparts.
#
code
expected result
1
json_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
Dependencies
This function uses the following Locutus functions:
exportfunction json_decode<T = JsonValue>(strJson: string): T | null { // discuss at: https://phpjs.org/functions/json_decode/ // parity verified: PHP 8.3 // 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 */
// 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: string): string { 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. // biome-ignore lint/security/noGlobalEval: needed for PHP port const parsed = eval('(' + text + ')') setPhpRuntimeEntry('last_error_json', 0) return parsed }
// usable by json_last_error() setPhpRuntimeEntry('last_error_json', 4) returnnull }
exportfunctionjson_decode(strJson) { // discuss at: https://phpjs.org/functions/json_decode/ // parity verified: PHP 8.3 // 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 */
// 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. // biome-ignore lint/security/noGlobalEval: needed for PHP port const parsed = eval('(' + text + ')') setPhpRuntimeEntry('last_error_json', 0) return parsed }
// usable by json_last_error() setPhpRuntimeEntry('last_error_json', 4) returnnull }
function json_decode<T = JsonValue>(strJson: string): T | null { // discuss at: https://phpjs.org/functions/json_decode/ // parity verified: PHP 8.3 // 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 */
// 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: string): string { 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. // biome-ignore lint/security/noGlobalEval: needed for PHP port const parsed = eval('(' + text + ')') setPhpRuntimeEntry('last_error_json', 0) return parsed }
// usable by json_last_error() setPhpRuntimeEntry('last_error_json', 4) returnnull }
// php/json/json_decode (target function module) functionjson_decode(strJson) { // discuss at: https://phpjs.org/functions/json_decode/ // parity verified: PHP 8.3 // 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 */
// 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. // biome-ignore lint/security/noGlobalEval: needed for PHP port const parsed = eval('(' + text + ')') setPhpRuntimeEntry('last_error_json', 0) return parsed }
// usable by json_last_error() setPhpRuntimeEntry('last_error_json', 4) returnnull }
Improve this function
Locutus is a community effort following
The McDonald's Theory:
we ship first iterations, hoping others will improve them.
If you see something that could be better, we'd love your contribution.