rfc:is_json

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
rfc:is_json [2022/08/14 22:06] – created juan_moralesrfc:is_json [2022/08/17 14:04] (current) juan_morales
Line 1: Line 1:
-====== PHP RFC: is_json() function ======+====== PHP RFC: is_json ======
   * Version: 0.9   * Version: 0.9
   * Date: 2022-08-14   * Date: 2022-08-14
Line 5: Line 5:
   * Status: Draft   * Status: Draft
   * First Published at: http://wiki.php.net/rfc/is_json   * First Published at: http://wiki.php.net/rfc/is_json
 +  * Implementation: https://github.com/php/php-src/pull/9355
  
-This is a suggested template for PHP Request for Comments (RFCs). Change this template to suit your RFC.  Not all RFCs need to be tightly specified.  Not all RFCs need all the sections below. +===== Preliminary note ===== 
-Read https://wiki.php.net/rfc/howto carefully!+ 
 +**If the name of the function needs to be change, I will change it; the functionality is the important thing here**
  
 ===== Introduction ===== ===== Introduction =====
-This RFC introduces a new function called is_json() to validate if an string is a valid json-string.+This RFC introduces a new function called is_json() to validate if an string contains a valid json.
  
-===== Fundaments ===== +Most userland implementations to achieve this are done using json_decode() which by design generates an object/array while parsing the string, ergo using memory and processing, that could be save.
-- Disadvantages of using json_decode or other regex approach. +
-- Reasons for this and projects emulating this with json_decode. +
-- Use existing JSON parser in a more isolated way.+
  
 ===== Proposal ===== ===== Proposal =====
-This RFC proposes a new function, that returns true if the given string is a valid json-string.+==== Description ==== 
 +<code php> 
 +is_json(string $json, int $depth = 512, int $flags = 0): bool 
 +</code> 
 + 
 +==== Parameters ==== 
 +**''json''** 
 + 
 +The json string being analyzed. 
 + 
 +This function only works with UTF-8 encoded strings. 
 + 
 +Note: 
 + 
 +PHP implements a superset of JSON as specified in the original » RFC 7159. 
 + 
 +**''depth''** 
 + 
 +Maximum nesting depth of the structure being decoded. 
 + 
 +**''flags''** 
 + 
 +Bitmask of **JSON_INVALID_UTF8_IGNORE**, **JSON_THROW_ON_ERROR**. The behavior of these constants is described on the [[https://www.php.net/manual/en/json.constants.php|JSON constants page]].
  
 Function description, examples, technical strategy, current JSON parser, etc. Function description, examples, technical strategy, current JSON parser, etc.
-....+ 
 +==== Return values ==== 
 + 
 +Returns **true** if the string passed contains a valid json, otherwise returns **false**. 
 + 
 +==== Extra behavior ==== 
 +
 +==== Examples ==== 
 +
 +===== Fundaments/Reasons ===== 
 +==== Disadvantages of using json_decode ==== 
 + 
 +By design, json_decode() generates an object/array while parsing the string, ergo using memory and processing for it, that is not needed if the only thing to discover is if a string contains a valid json. 
 + 
 +==== Disadvantages of using regex ==== 
 + 
 +Using a regex for this task forces different, error-prone, hard to maintain, implementations. 
 + 
 +==== Needs from major projects and developers ==== 
 + 
 +In the "References" section, there is a list of major open-source php projects needing this feature; also in th mntioned section can find a link to one of the most popular StackOverflow questions, which somehow reflects the need from our developers to have a feature like this included. 
 + 
 +==== Complexity added in the core ==== 
 + 
 +At the moment, there is a JSON parser in the core, used by json_decode to do its job, so there is no need to write a new JSON parser for this RFC; the proposed function will use the existing JSON parser exclusively to parse an string without generating any object/array in memory for it.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 47: Line 92:
  
 ===== References ===== ===== References =====
-- (To be done later+ 
--- Links to external referencesdiscussions or RFCs +==== Major Open-Source projects that will benefit out of this ==== 
--- Links to major open-source projects emulating this function using json_decode + 
--- Link to Stackoverflow pointing the question, which this proposed function satisfy the needs+[[https://github.com/symfony/symfony/blob/870eeb975feb1abb4b8a1722e1fd57beeab2b230/src/Symfony/Component/Validator/Constraints/JsonValidator.php|Symfony Framework]] 
 + 
 +<code php> 
 +class JsonValidator extends ConstraintValidator 
 +</code> 
 + 
 +[[https://github.com/laravel/framework/blob/302a579f00ebcb2573f481054cbeadad9c970605/src/Illuminate/Validation/Concerns/ValidatesAttributes.php|Laravel Framework]] 
 + 
 +<code php> 
 +    public function validateJson($attribute, $value
 +    { 
 +        if (is_array($value)) { 
 +            return false; 
 +        } 
 + 
 +        if (! is_scalar($value) && ! is_null($value) && ! method_exists($value, '__toString')) { 
 +            return false; 
 +        } 
 + 
 +        json_decode($value); 
 + 
 +        return json_last_error() === JSON_ERROR_NONE; 
 +    } 
 +</code> 
 + 
 +[[https://github.com/laravel/framework/blob/61eac9cae4717699ecb3941b16c3d775820d4ca2/src/Illuminate/Support/Str.php|Laravel Framework]] 
 + 
 +<code php> 
 +    public static function isJson($value) 
 +    { 
 +</code> 
 + 
 +[[https://github.com/magento/magento2/blob/7c6b6365a3c099509d6f6e6c306cb1821910aab0/app/code/Magento/User/Block/Role/Grid/User.php|Magento]] 
 + 
 +<code php> 
 +    private function getJSONString($input) 
 +    { 
 +        $output = json_decode($input); 
 +        return $output ? $this->_jsonEncoder->encode($output) : '{}'; 
 +    } 
 +</code> 
 + 
 +[[https://github.com/magento/magento2/blob/7c6b6365a3c099509d6f6e6c306cb1821910aab0/lib/internal/Magento/Framework/DB/DataConverter/SerializedToJson.php|Magento]] 
 + 
 +<code php> 
 +    protected function isValidJsonValue($value) 
 +    { 
 +        if (in_array($value['null', 'false', '0', '""', '[]']) 
 +            || (json_decode($value) !== null && json_last_error() === JSON_ERROR_NONE) 
 +        ) { 
 +            return true; 
 +        } 
 +        //JSON last error reset 
 +        json_encode([]); 
 +        return false; 
 +    } 
 +</code> 
 + 
 +[[https://github.com/magento/magento2/blob/7c6b6365a3c099509d6f6e6c306cb1821910aab0/lib/internal/Magento/Framework/Serialize/JsonValidator.php|Magento]] 
 + 
 +<code php> 
 +    public function isValid($string) 
 +    { 
 +        if ($string !== false && $string !== null && $string !== '') { 
 +            json_decode($string); 
 +            if (json_last_error() === JSON_ERROR_NONE) { 
 +                return true; 
 +            } 
 +        } 
 +        return false; 
 +    } 
 +</code> 
 + 
 + 
 +[[https://github.com/getgrav/grav/blob/3e7f67f589267e61f823d19824f3ee1b9a8a38ff/system/src/Grav/Common/Data/Validation.php|getgrav]] 
 + 
 +<code php> 
 +    public static function validateJson($value, $params) 
 +    { 
 +        return (bool) (@json_decode($value)); 
 +    } 
 +</code> 
 + 
 + 
 +[[https://github.com/symfony/http-kernel/blob/94986633e4c3e7facb7defbd094a2e1170486ab5/DataCollector/RequestDataCollector.php|Symfony htp-kernel ]] 
 + 
 +<code php> 
 +    public function getPrettyJson() 
 +    { 
 +        $decoded = json_decode($this->getContent()); //<------ here  
 + 
 +        return \JSON_ERROR_NONE === json_last_error() ? json_encode($decoded, \JSON_PRETTY_PRINT) : null; 
 +    } 
 +</code> 
 + 
 + 
 +[[https://github.com/Respect/Validation/blob/3dcd859d986f1b586b5539ea19962723ab7352ed/library/Rules/Json.php|Respect / Validation]] 
 + 
 +<code php> 
 +final class Json extends AbstractRule 
 +
 +    /** 
 +     * {@inheritDoc} 
 +     */ 
 +    public function validate($input): bool 
 +    { 
 +        if (!is_string($input) || $input === '') { 
 +            return false; 
 +        } 
 + 
 +        json_decode($input); 
 + 
 +        return json_last_error() === JSON_ERROR_NONE; 
 +    } 
 +
 +</code> 
 + 
 +[[https://github.com/Respect/Validation/blob/3dcd859d986f1b586b5539ea19962723ab7352ed/library/Rules/Json.php|Respect / Validation]] 
 + 
 +<code php> 
 +final class Json extends AbstractRule 
 +
 +    /** 
 +     * {@inheritDoc} 
 +     */ 
 +    public function validate($input): bool 
 +    { 
 +        if (!is_string($input) || $input === '') { 
 +            return false; 
 +        } 
 + 
 +        json_decode($input); 
 + 
 +        return json_last_error() === JSON_ERROR_NONE; 
 +    } 
 +
 +</code> 
 + 
 +[[https://github.com/humhub/humhub/blob/26d7e2667a9317057abe335a056ac8e8f4d675fb/protected/humhub/modules/web/security/controllers/ReportController.php|humhub]] 
 + 
 + 
 +<code php> 
 +    public function actionIndex() 
 +    { 
 +        Yii::$app->response->statusCode = 204; 
 + 
 +        if(!SecuritySettings::isReportingEnabled()) { 
 +            return; 
 +        } 
 + 
 +        $json_data = file_get_contents('php://input'); 
 +        if ($json_data = json_decode($json_data)) { //<----- json_decode() just to check if is valid json-string only 
 +            $json_data = json_encode($json_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); 
 +            $json_data = preg_replace('/\'nonce-[^\']*\'/', "'nonce-xxxxxxxxxxxxxxxxxxxxxxxx'", $json_data); 
 +            Yii::error($json_data, 'web.security'); 
 +        } 
 +    } 
 +</code> 
 + 
 +[[https://github.com/PrestaShop/PrestaShop/blob/24f9e510ecb0cb002ac3f4834f3210e8d9359899/classes/Validate.php|Prestashop]] 
 + 
 +<code php> 
 +    public static function isJson($string) 
 +    { 
 +        json_decode($string); 
 + 
 +        return json_last_error() == JSON_ERROR_NONE; 
 +    } 
 +</code> 
 + 
 +[[https://github.com/wp-cli/wp-cli/blob/f3e4b0785aa3d3132ee73be30aedca8838a8fa06/php/utils.php|Wordpress CLI]] 
 + 
 +<code php> 
 +function is_json( $argument, $ignore_scalars = true ) { 
 +    if ( ! is_string( $argument ) || '' === $argument ) { 
 +        return false; 
 +    } 
 + 
 +    if ( $ignore_scalars && ! in_array( $argument[0], [ '{', '[' ], true ) ) { 
 +        return false; 
 +    } 
 + 
 +    json_decode( $argument, $assoc = true ); 
 + 
 +    return json_last_error() === JSON_ERROR_NONE; 
 +
 +</code> 
 + 
 +[[https://github.com/joomla/joomla-cms/blob/09d14c65f25f9bc76f2698e69c4d7b35f43bc848/libraries/src/Form/Field/AccessiblemediaField.php|JOOMLA CMS]] 
 + 
 +<code php> 
 +if (\is_string($value)) { 
 +    json_decode($value); //<------ HERE 
 + 
 +    // Check if value is a valid JSON string. 
 +    if ($value !== '' && json_last_error() !== JSON_ERROR_NONE) { 
 +        /** 
 +         * If the value is not empty and is not a valid JSON string, 
 +         * it is most likely a custom field created in Joomla 3 and 
 +         * the value is a string that contains the file name. 
 +        */ 
 +        if (is_file(JPATH_ROOT . '/' . $value)) { 
 +            $value = '{"imagefile":"' . $value . '","alt_text":""}'; 
 +        } else { 
 +            $value = ''; 
 +        } 
 +    } 
 + 
 +</code> 
 + 
 + 
 + 
 +==== Stackoverflow questions related to this ==== 
 + 
 + 
 +In PHP, this question is one of the most high ranked questions related to json && php in stackoverflow"Fastest way to check if a string is JSON in PHP?". [[https://stackoverflow.com/questions/6041741/fastest-way-to-check-if-a-string-is-json-in-php|The question]] 
 + 
 +Viewed 484k times. [[https://stackoverflow.com/questions/tagged/php%20json?sort=MostVotes&edited=true|The ranking]] 
 + 
 +Person asking how to do exactly this, also providing a real use case; eventhough in python, the programming language is not important. [[https://stackoverflow.com/questions/5508509/how-do-i-check-if-a-string-is-valid-json-in-python|In Python]] 
 + 
 +Someone has also doing exactly this , in JAVA. [[https://stackoverflow.com/questions/3679479/check-if-file-is-json-java|In Java]]
  
 ===== Rejected Features ===== ===== Rejected Features =====
 - No rejected features currently. - No rejected features currently.
rfc/is_json.1660514798.txt.gz · Last modified: 2022/08/14 22:06 by juan_morales