Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:118326 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 81076 invoked from network); 31 Jul 2022 11:15:22 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 31 Jul 2022 11:15:22 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 13B7718037E for ; Sun, 31 Jul 2022 06:14:39 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-yb1-f178.google.com (mail-yb1-f178.google.com [209.85.219.178]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sun, 31 Jul 2022 06:14:38 -0700 (PDT) Received: by mail-yb1-f178.google.com with SMTP id i62so13192035yba.5 for ; Sun, 31 Jul 2022 06:14:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=KZJE6MMtMKDiQbiu7umJ5V+6sxZsIYo8x3kY9RHuCgU=; b=NVdT0KZkfH/WuV2l2Z4MRc2unpugROJP1MWP4mRoYppSIuIbWGpGSfXmS+L9cAe34c wufJ8aXMPvcIVDpJ+gzqM6rb/ykRfULmixOPe9Bkv7L/crkbMY51SoE6JAkufMZc7f30 ABEGSwXt9h7l8PqAHn+/A9QM/2XbEeziYS+Klq0BjPI5y2xvCkJSu1qFymGZIpEEEdbc 1nt5zQ8vMg5icgtCvHWA/B3RKBMDmGetizGUPPIEsYoIWD4zz26RvPf26FRIj7T4HpX7 1cp02EMf7TjP7fx+NkrMgzQJ7nki2nEZY1IIr3EbbtXtCKqQ4L2fEMM39G/RTvikfxL4 v/RQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=KZJE6MMtMKDiQbiu7umJ5V+6sxZsIYo8x3kY9RHuCgU=; b=mRoeTljasywf6xTtcqlNeA0TJV2bfj8xNuqqm+/5cccf3CLDn0/Ns37xzoq5Drwulz pe8nEA5K7cMBSbgY46OWPw1w0FLLEB6o3NO5xMxANHk6Hgio62N4tEbl5x/eYheGMPui qnQrFEtL402QdEBIzj+P61aCv1A+K6jH6ZojOGgIZo4J8q4oqvJYWP8v5fhoLULBcYUQ sTY0bnDt1BOpyDFfid7cXJqV2Xo3d/CZIntN9VKalGj1xxffdE91gq9CmZU2P7Rh3+7q 5e7ka/2QrdHLQed4juN3fNm1E5uWXjjlcZghAdMKin7LJCiT8Sj/5/Uib9+Uz/8uvt6t u34w== X-Gm-Message-State: ACgBeo0yfoyVmorh6rFXNsiFE3vxYnWHXNNtoyJV0GotHFDFznPpl7bj RyXjX2N2HtO0ydeNXj+yVYPyK5XyHZaFWtAxIE0= X-Google-Smtp-Source: AA6agR5LnHjAdMxyTvxtWzL9HdQGNWnTT/pKzlXUnzWjEkCmxuH7oQPG7mzIio97ke1u/6mFMF3jyPBfQfukMe6ARnU= X-Received: by 2002:a25:abb3:0:b0:671:6efb:e4c3 with SMTP id v48-20020a25abb3000000b006716efbe4c3mr8299155ybi.640.1659273277879; Sun, 31 Jul 2022 06:14:37 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Sun, 31 Jul 2022 15:14:27 +0200 Message-ID: To: Deleu Cc: David Gebler , Nikita Popov , PHP internals Content-Type: multipart/alternative; boundary="0000000000005037cf05e519aaee" Subject: Re: [PHP-DEV] RFC Idea - is_json - looking for feedback From: dev.juan.morales@gmail.com (juan carlos morales) --0000000000005037cf05e519aaee Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable El dom, 31 jul 2022 a las 0:56, Deleu () escribi=C3=B3: > > > On Sat, Jul 30, 2022, 4:48 PM David Gebler wrote: > >> >> >> What I'm asking is what's the practical use for this proposed function? >> Where are you likely to need to know if a string is valid JSON but not >> have >> to (try to, with error handling) parse it almost immediately afterwards >> anyway? >> > > I'm still on the fence over the general idea, but I thought I could at > least address this question in particular. > > I can definitely see it's usefulness on public HTTP API ingesting data > (specially large data) where if the payload is a valid JSON, it gets stor= ed > and processed by a background queue, making it so that the HTTP layer can > either reject the request with a 4xx status or accept it and only truly > decode it on a separate process that may even be hosted by a separate > server with larger memory size. > Before starting, I want to thank all for taking time from your time, to give me a feedback, I sincerely respect that, so ... thanks! Sorry for the long message, but I have the feeling that ... this is it, is now ... or it will not be, at least not now, so ... here my best effort; even though, I dont put aside the possibility that I might have an offuscated view/opinion regarding my proposal, so is possible that I might not see the things right ... you know .. I am human after all. So, enough of prologue and let's start .... # Why would I have code that checks if a json-string is a valid json, if I will not use the content inside it? (or something like that) - Some of you , asked me this question. - That depends on the infinite amout of use cases that the human brain can imagine, that is why I say that is not the right approach to discuss this topic. # Why this change then? - Is web related, ergo, is PHP related. - It does not add complexity into PHP, with this functionality we are using the existing JSON parser that exists in PHP at the moment, the only thing we do is to create an interface between "userland" and the parser itself, without the need to use memory as json_decode() is using to check if a string is a valid json-string or not. ## Proposed functionality (proposed, subject to changes for sure, as now I have only a working and dirty prototype for this) function is_json(string $json, int $flags): bool {} Returns: TRUE if json-string is valid json, otherwise returns FALSE. Exceptions: Optionally set, for the same or subset of exceptions of the actual json_decode(), like the one Syntax Error for example. So far this is it, subject to changes for sure. # Real open-source project over github using json_decode() just to check if a json-string is valid ... and nothing else than that. - I provide here use cases from major projects, where they ned to have code that has to be able to check if an string is a valid JSON and nothing else than that. - Please check the link to see full code - I provide here some small snippets from the link I provide - We are not discussing here how they implemented the code, what I want to show here is that there is a need to check if an string is a valid JSON-string without th need to create an object/array out of it. - Also, we are not discussing if they are mejor projects or not. They are listed in github as major projects, with stars and a big community of users and developers maintaining them. - On some snippets I wrote some notes too, because on some of them is not obvious how a funciton like the one I propose could be useful. ## Symfony Framework https://github.com/symfony/symfony/blob/870eeb975feb1abb4b8a1722e1fd57beeab= 2b230/src/Symfony/Component/Validator/Constraints/JsonValidator.php ``` class JsonValidator extends ConstraintValidator ... ... ... ``` ## Laravel Framework https://github.com/laravel/framework/blob/302a579f00ebcb2573f481054cbeadad9= c970605/src/Illuminate/Validation/Concerns/ValidatesAttributes.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() =3D=3D=3D JSON_ERROR_NONE; } ``` https://github.com/laravel/framework/blob/61eac9cae4717699ecb3941b16c3d7758= 20d4ca2/src/Illuminate/Support/Str.php ``` public static function isJson($value) { ``` ## Magento https://github.com/magento/magento2/blob/7c6b6365a3c099509d6f6e6c306cb18219= 10aab0/app/code/Magento/User/Block/Role/Grid/User.php ``` private function getJSONString($input) { $output =3D json_decode($input); return $output ? $this->_jsonEncoder->encode($output) : '{}'; } ``` https://github.com/magento/magento2/blob/7c6b6365a3c099509d6f6e6c306cb18219= 10aab0/lib/internal/Magento/Framework/DB/DataConverter/SerializedToJson.php ``` protected function isValidJsonValue($value) { if (in_array($value, ['null', 'false', '0', '""', '[]']) || (json_decode($value) !=3D=3D null && json_last_error() =3D= =3D=3D JSON_ERROR_NONE) ) { return true; } //JSON last error reset json_encode([]); return false; } ``` https://github.com/magento/magento2/blob/7c6b6365a3c099509d6f6e6c306cb18219= 10aab0/lib/internal/Magento/Framework/Serialize/JsonValidator.php ``` public function isValid($string) { if ($string !=3D=3D false && $string !=3D=3D null && $string !=3D= =3D '') { json_decode($string); if (json_last_error() =3D=3D=3D JSON_ERROR_NONE) { return true; } } return false; } ``` ## getgrav https://github.com/getgrav/grav/blob/3e7f67f589267e61f823d19824f3ee1b9a8a38= ff/system/src/Grav/Common/Data/Validation.php ``` public static function validateJson($value, $params) { return (bool) (@json_decode($value)); } ``` ## Symfony / http-kernel https://github.com/symfony/http-kernel/blob/94986633e4c3e7facb7defbd094a2e1= 170486ab5/DataCollector/RequestDataCollector.php ``` public function getPrettyJson() { $decoded =3D json_decode($this->getContent()); //<------ here they decode, just to check if is valid json-string or not, that is th reason of this line. return \JSON_ERROR_NONE =3D=3D=3D json_last_error() ? json_encode($decoded, \JSON_PRETTY_PRINT) : null; } ``` ## Respect / Validation https://github.com/Respect/Validation/blob/3dcd859d986f1b586b5539ea19962723= ab7352ed/library/Rules/Json.php ``` final class Json extends AbstractRule { /** * {@inheritDoc} */ public function validate($input): bool { if (!is_string($input) || $input =3D=3D=3D '') { return false; } json_decode($input); return json_last_error() =3D=3D=3D JSON_ERROR_NONE; } } ``` https://github.com/Respect/Validation/blob/3dcd859d986f1b586b5539ea19962723= ab7352ed/library/Rules/Json.php ``` final class Json extends AbstractRule { /** * {@inheritDoc} */ public function validate($input): bool { if (!is_string($input) || $input =3D=3D=3D '') { return false; } json_decode($input); return json_last_error() =3D=3D=3D JSON_ERROR_NONE; } } ``` ## humhub https://github.com/humhub/humhub/blob/26d7e2667a9317057abe335a056ac8e8f4d67= 5fb/protected/humhub/modules/web/security/controllers/ReportController.php ``` public function actionIndex() { Yii::$app->response->statusCode =3D 204; if(!SecuritySettings::isReportingEnabled()) { return; } $json_data =3D file_get_contents('php://input'); if ($json_data =3D json_decode($json_data)) { //<----- here they json_decode() just to check if is valid json-string only, am I right? $json_data =3D json_encode($json_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); $json_data =3D preg_replace('/\'nonce-[^\']*\'/', "'nonce-xxxxxxxxxxxxxxxxxxxxxxxx'", $json_data); Yii::error($json_data, 'web.security'); } } ``` ## Prestashop https://github.com/PrestaShop/PrestaShop/blob/24f9e510ecb0cb002ac3f4834f321= 0e8d9359899/classes/Validate.php ``` public static function isJson($string) { json_decode($string); return json_last_error() =3D=3D JSON_ERROR_NONE; } ``` ## Wordpress CLI https://github.com/wp-cli/wp-cli/blob/f3e4b0785aa3d3132ee73be30aedca8838a8f= a06/php/utils.php ``` function is_json( $argument, $ignore_scalars =3D true ) { if ( ! is_string( $argument ) || '' =3D=3D=3D $argument ) { return false; } if ( $ignore_scalars && ! in_array( $argument[0], [ '{', '[' ], true ) ) { return false; } json_decode( $argument, $assoc =3D true ); return json_last_error() =3D=3D=3D JSON_ERROR_NONE; } ``` ## JOOMLA CMS https://github.com/joomla/joomla-cms/blob/09d14c65f25f9bc76f2698e69c4d7b35f= 43bc848/libraries/src/Form/Field/AccessiblemediaField.php ``` if (\is_string($value)) { json_decode($value); //<---------------------------------------------------------- HERE // Check if value is a valid JSON string. if ($value !=3D=3D '' && json_last_error() !=3D=3D 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 =3D '{"imagefile":"' . $value . '","alt_text":""}'; } else { $value =3D ''; } } ``` # 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?" ### The question https://stackoverflow.com/questions/6041741/fastest-way-to-check-if-a-strin= g-is-json-in-php Viewed 484k times ### The ranking https://stackoverflow.com/questions/tagged/php%20json?sort=3DMostVotes&edit= ed=3Dtrue ## 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-v= alid-json-in-python ## Someone has also doing exactly this , in JAVA https://stackoverflow.com/questions/3679479/check-if-file-is-json-java --0000000000005037cf05e519aaee--