检查字符串是否是PHP中的JSON的最快方法?

Kir*_*met 355 php error-handling json jsonresult json-deserialization

我需要一种非常非常快速的检查字符串是否为JSON的方法.我觉得这不是最好的方法:

function isJson($string) {
    return ((is_string($string) &&
            (is_object(json_decode($string)) ||
            is_array(json_decode($string))))) ? true : false;
}
Run Code Online (Sandbox Code Playgroud)

任何表演爱好者都想改进这种方法吗?

Hen*_*sel 542

function isJson($string) {
 json_decode($string);
 return (json_last_error() == JSON_ERROR_NONE);
}
Run Code Online (Sandbox Code Playgroud)

  • 检查字符串的第一个字符为`{`,`[或任何其他文字的第一个符号,当许多传入的字符串被认为是非JSON时,可能会大大加快这一点. (92认同)
  • 请注意,无论您将其指定为字符串还是真实数字,此函数也会对任何数字返回true.`6.5 = true,'300'= true,9 = true`等.所以这可能是一个有效的JSON值,但如果你只想检查带有`{}的有效JSON字符串,那么函数可能不会按预期运行.或者`[]`; (22认同)
  • $ phone ='021234567'; 的var_dump(isJson($电话)); 回归真不!它应该返回false. (20认同)
  • 看起来每个人都喜欢这个答案.任何解释为什么? (18认同)
  • 我相信需要使用PHP 5.3>来使用json_last_error函数 (8认同)
  • 值得注意的是,这在理论上是正确的.不幸的是,PHP的`json_decode`函数有许多错误,这将允许以奇怪的方式解析无效的JSON.`isJson('0123')`应该返回`false`,因为`0123`不是JSON,但是`isJson('123')`应该返回'true`,因为`123`*是*JSON.似乎有些人不知道[JSON允许值不仅仅是一个对象或数组](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf) .有效的JSON值可以是对象,数组,数字,字符串,布尔值和"null". (7认同)
  • php 8.3 将实现名为 json_validate() 的新函数来验证字符串是否包含有效的 json。 (3认同)
  • 我认为它很好,因为它不依赖于启发式,使用本机PHP功能,并且可以像你将要获得的那样面向未来; 它只是直接告诉你解码字符串是否有任何错误.没有错误=>有效的JSON. (2认同)
  • 对不起。由于上述原因,我对此投反对票。取决于您对函数的确切要求,但如果正在执行任何类型的用户输入有效性,则可能存在一个小漏洞。 (2认同)
  • 当然,它只需要 `if (is_numeric($string)) return false;` 作为函数的第一行来捕获仅数字 $string 值? (2认同)
  • 我相信这个答案强调,在大多数情况下,测试json-ness可能是不必要的甚至是有害的 - 只需解码所有内容并处理错误.如果你根据它是否是标量来有条件地编码你的数据,你应该只是*编码*所有东西,因为json对标量数据的处理非常简单.如果其他数据类型更常见,您应该尝试在尝试json解码之前先处理这些数据类型. (2认同)

Mad*_*ota 147

回答问题

该函数json_last_error返回JSON编码和解码期间发生的最后一个错误.因此,检查有效JSON的最快方法是

// decode the JSON data
// set second parameter boolean TRUE for associative array output.
$result = json_decode($json);

if (json_last_error() === JSON_ERROR_NONE) {
    // JSON is valid
}

// OR this is equivalent

if (json_last_error() === 0) {
    // JSON is valid
}
Run Code Online (Sandbox Code Playgroud)

请注意,json_last_errorPHP> = 5.3.0仅支持.

完整的程序来检查确切的错误

在开发期间知道确切的错误总是好的.这是完整的程序,以检查基于PHP文档的确切错误.

function json_validate($string)
{
    // decode the JSON data
    $result = json_decode($string);

    // switch and check possible JSON errors
    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            $error = ''; // JSON is valid // No error has occurred
            break;
        case JSON_ERROR_DEPTH:
            $error = 'The maximum stack depth has been exceeded.';
            break;
        case JSON_ERROR_STATE_MISMATCH:
            $error = 'Invalid or malformed JSON.';
            break;
        case JSON_ERROR_CTRL_CHAR:
            $error = 'Control character error, possibly incorrectly encoded.';
            break;
        case JSON_ERROR_SYNTAX:
            $error = 'Syntax error, malformed JSON.';
            break;
        // PHP >= 5.3.3
        case JSON_ERROR_UTF8:
            $error = 'Malformed UTF-8 characters, possibly incorrectly encoded.';
            break;
        // PHP >= 5.5.0
        case JSON_ERROR_RECURSION:
            $error = 'One or more recursive references in the value to be encoded.';
            break;
        // PHP >= 5.5.0
        case JSON_ERROR_INF_OR_NAN:
            $error = 'One or more NAN or INF values in the value to be encoded.';
            break;
        case JSON_ERROR_UNSUPPORTED_TYPE:
            $error = 'A value of a type that cannot be encoded was given.';
            break;
        default:
            $error = 'Unknown JSON error occured.';
            break;
    }

    if ($error !== '') {
        // throw the Exception or exit // or whatever :)
        exit($error);
    }

    // everything is OK
    return $result;
}
Run Code Online (Sandbox Code Playgroud)

使用有效的JSON INPUT进行测试

$json = '[{"user_id":13,"username":"stack"},{"user_id":14,"username":"over"}]';
$output = json_validate($json);
print_r($output);
Run Code Online (Sandbox Code Playgroud)

有效输出

Array
(
    [0] => stdClass Object
        (
            [user_id] => 13
            [username] => stack
        )

    [1] => stdClass Object
        (
            [user_id] => 14
            [username] => over
        )
)
Run Code Online (Sandbox Code Playgroud)

使用无效的JSON进行测试

$json = '{background-color:yellow;color:#000;padding:10px;width:650px;}';
$output = json_validate($json);
print_r($output);
Run Code Online (Sandbox Code Playgroud)

无效的输出

Syntax error, malformed JSON.
Run Code Online (Sandbox Code Playgroud)

额外注意事项(PHP> = 5.2 && PHP <5.3.0)

由于json_last_errorPHP 5.2不支持,您可以检查编码或解码是否返回布尔值FALSE.这是一个例子

// decode the JSON data
$result = json_decode($json);
if ($result === FALSE) {
    // JSON is invalid
}
Run Code Online (Sandbox Code Playgroud)

希望这是有帮助的.快乐的编码!


小智 75

你真正需要做的就是......

if (is_object(json_decode($MyJSONArray))) 
    { 
        ... do something ...
    }
Run Code Online (Sandbox Code Playgroud)

此请求甚至不需要单独的功能.只需在json_decode周围包装is_object并继续.似乎这个解决方案让人们对此过于考虑.

  • @ggutenberg is_array()用于json_decode($ json,true); (21认同)
  • 请注意:"此请求甚至不需要单独的功能." 严格来说,没有解决方案需要单独的功能.函数的要点是_not_使多行代码看起来像一行代码.该功能的目的是使JSON检查过程在应用程序的任何地方都是标准的,这样不同的程序员(或同一个程序员随着时间的推移)就不会在程序流程的不同阶段使用不同的检查程序. (9认同)
  • @RomanM.Kos 只是要清楚,如果数组是一个简单的数组,那么除了 `is_object` 之外你还需要使用 `is_array`,否则对于编码为 JSON 的简单数组,`is_object` 将返回 false。所以@ggutenberg 在这种情况下是正确的。将 true 参数传递给 `json_decode` 会强制将对象作为数组返回。从理论上讲,您可以始终强制解码为数组并只检查“is_array”,这应该可以工作。 (3认同)

mar*_*rio 70

使用json_decode"探测"它实际上可能不是最快的方式.如果它是一个深度嵌套的结构,那么实例化大量的数组对象只是扔掉它们是浪费内存和时间.

因此,使用preg_matchRFC4627正则表达式可能更快,以确保有效性:

  // in JS:
  var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
         text.replace(/"(\\.|[^"\\])*"/g, '')));
Run Code Online (Sandbox Code Playgroud)

在PHP中也一样:

  return !preg_match('/[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]/',
       preg_replace('/"(\\.|[^"\\\\])*"/', '', $json_string));
Run Code Online (Sandbox Code Playgroud)

然而,这里没有足够的性能爱好者来打扰基准测试.

  • 完整的递归正则表达式来验证JSON:http://stackoverflow.com/questions/2583472/regex-to-validate-json/3845829#3845829 - 但事实证明,PHP的`json_decode`总是比PCRE正则表达式更快.(虽然它没有得到很好的优化,但没有发现合成测试,并且可能在Perl中表现不同......) (10认同)
  • @mario好的,我明白了.所以基本上,PHP会在reg-exp引擎看到之前转义反斜杠.就reg-exp引擎而言,字符串中的反斜杠数量是我们人类看到的数量的一半._"就像reg-exp已经不够复杂了"_ (4认同)
  • @vee是的,谢谢你的说明.但是让我们把它保存在这里[错误],所以没有人真正在生产中使用它. (3认同)
  • 我很好奇这是否真的比使用 json_decode 来查看字符串是否是有效的 JSON 更快,所以我运行了一些基准测试。我对使用 json_encode 编码的二维数组运行了 100,000 次。`PHP 版本:5.5.34 平台:Darwin -------------------------------------- test_json_decode: 5.608 秒 test_regex : 10.428 秒` (2认同)

Cyr*_*ril 37

如果您的字符串表示json数组或对象,则返回true:

function isJson($str) {
    $json = json_decode($str);
    return $json && $str != $json;
}
Run Code Online (Sandbox Code Playgroud)

它拒绝只包含数字,字符串或布尔值的json字符串,尽管这些字符串在技术上是有效的json.

var_dump(isJson('{"a":5}')); // bool(true)
var_dump(isJson('[1,2,3]')); // bool(true)
var_dump(isJson('1')); // bool(false)
var_dump(isJson('1.5')); // bool(false)
var_dump(isJson('true')); // bool(false)
var_dump(isJson('false')); // bool(false)
var_dump(isJson('null')); // bool(false)
var_dump(isJson('hello')); // bool(false)
var_dump(isJson('')); // bool(false)
Run Code Online (Sandbox Code Playgroud)

这是我能想到的最短路.

  • 为什么其他人都有这么长的啰嗦答案?谢谢. (3认同)
  • @Cyril,抱歉,我错过了这种情况,因为我的测试函数包括在调用“json_decode”之前对函数进行短路的额外检查。由于“hello”字符串触发 JSON 错误,因此函数的输出为“NULL”,因此额外的“!is_null”检查足以使用测试数据生成正确的结果:“return $json !== false &amp;&amp;” !is_null($json) &amp;&amp; $str != $json;` (3认同)
  • 简单,可爱!没有检查“最快的方式”或性能方面,但这肯定涵盖了我检查过的所有情况。这是臭名昭著的谚语**“不要用大锤敲碎坚果”**的经典示例。从程序员的角度来看,保持代码简单、简短和易于理解总是更好,性能与简单性是本线程范围之外的另一个争论。 (2认同)

Moh*_*een 20

我使用的最简单,最快捷的方法是遵循;

$json_array = json_decode( $raw_json , true );

if( $json_array == NULL )   //check if it was invalid json string
    die ('Invalid');  // Invalid JSON error

 // you can execute some else condition over here in case of valid JSON
Run Code Online (Sandbox Code Playgroud)

这是因为如果输入的字符串不是json或无效的json ,则 json_decode()返回NULL.


简单的函数来验证JSON

如果必须在多个位置验证JSON,则始终可以使用以下功能.

function is_valid_json( $raw_json ){
    return ( json_decode( $raw_json , true ) == NULL ) ? false : true ; // Yes! thats it.
}
Run Code Online (Sandbox Code Playgroud)

在上面的函数中,如果它是有效的JSON,你将得到回报.

  • `json_decode('null')== NULL`和`null`是一个有效的JSON值. (3认同)
  • 与其信任一些未经验证的网站,[考虑查阅不同意的规范(第 2 页)](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf)。或者,在您的开发控制台中尝试`JSON.parse('null')`。 (2认同)

Ahm*_*gle 17

function is_json($str){ 
    return json_decode($str) != null;
}
Run Code Online (Sandbox Code Playgroud)

检测到无效编码时,http://tr.php.net/manual/en/function.json-decode.php返回值为null.

  • 它也会不正确地为"null"返回null(这不是有效的JSON,但对于json_decode可能完全"有效").去搞清楚. (4认同)
  • @ user166390,[`json_decode('null')`根据规范是有效的JSON](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf),应该返回`null`的值. (2认同)

Rou*_*ica 14

昨天在我的工作中遇到类似的事情后,我发现了这个问题。最后,我的解决方案是上述一些方法的混合:

function is_JSON($string) {

  return (is_null(json_decode($string))) ? FALSE : TRUE;

}
Run Code Online (Sandbox Code Playgroud)

  • [Is null valid JSON?](/sf/answers/2738746811/)的相关问题。 (2认同)
  • is_null 已经返回 bool,可以缩短为 `return is_null(json_decode($string));` (2认同)

upf*_*ful 11

您必须验证输入以确保您传递的字符串不为空,实际上是一个字符串.空字符串无效JSON.

function is_json($string) {
  return !empty($string) && is_string($string) && is_array(json_decode($string, true)) && json_last_error() == 0;
}
Run Code Online (Sandbox Code Playgroud)

我认为在PHP中确定JSON对象是否有数据更为重要,因为要使用您需要调用的数据json_encode()json_decode().我建议拒绝空的JSON对象,这样就不会不必要地对空数据运行编码和解码.

function has_json_data($string) {
  $array = json_decode($string, true);
  return !empty($string) && is_string($string) && is_array($array) && !empty($array) && json_last_error() == 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 截至 2023 年 6 月,json_validate() 正式成为 PHP 8.3 Alpha-2 版本的一部分。 (3认同)

Mat*_*son 10

将 PHPBench 与以下类一起使用,实现了以下结果:

<?php

declare(strict_types=1);

/**
 * @Revs(1000)
 * @Iterations(100)
 */
class BenchmarkJson
{
    public function benchCatchValid(): bool
    {
        $validJson = '{"validJson":true}';
        try {
            json_decode($validJson, true, 512, JSON_THROW_ON_ERROR);
            return true;
        } catch(\JsonException $exception) {}
        return false;
    }

    public function benchCatchInvalid(): bool
    {
        $invalidJson = '{"invalidJson"';
        try {
            json_decode($invalidJson, true, 512, JSON_THROW_ON_ERROR);
            return true;
        } catch(\JsonException $exception) {}
        return false;
    }

    public function benchLastErrorValid(): bool
    {
        $validJson = '{"validJson":true}';
        json_decode($validJson, true);
        return (json_last_error() === JSON_ERROR_NONE);
    }

    public function benchLastErrorInvalid(): bool
    {
        $invalidJson = '{"invalidJson"';
        json_decode($invalidJson, true);
        return (json_last_error() === JSON_ERROR_NONE);
    }

    public function benchNullValid(): bool
    {
        $validJson = '{"validJson":true}';
        return (json_decode($validJson, true) !== null);
    }

    public function benchNullInvalid(): bool
    {
        $invalidJson = '{"invalidJson"';
        return (json_decode($invalidJson, true) !== null);
    }
}

Run Code Online (Sandbox Code Playgroud)
6 subjects, 600 iterations, 6,000 revs, 0 rejects, 0 failures, 0 warnings
(best [mean mode] worst) = 0.714 [1.203 1.175] 1.073 (?s)
?T: 721.504?s ?SD/r 0.089?s ?RSD/r: 7.270%
suite: 1343ab9a3590de6065bc0bc6eeb344c9f6eba642, date: 2020-01-21, stime: 12:50:14
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+
| benchmark     | subject               | set | revs | its | mem_peak   | best    | mean    | mode    | worst   | stdev   | rstdev | diff  |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+
| BenchmarkJson | benchCatchValid       | 0   | 1000 | 100 | 2,980,168b | 0.954?s | 1.032?s | 1.016?s | 1.428?s | 0.062?s | 6.04%  | 1.33x |
| BenchmarkJson | benchCatchInvalid     | 0   | 1000 | 100 | 2,980,184b | 2.033?s | 2.228?s | 2.166?s | 3.001?s | 0.168?s | 7.55%  | 2.88x |
| BenchmarkJson | benchLastErrorValid   | 0   | 1000 | 100 | 2,980,184b | 1.076?s | 1.195?s | 1.169?s | 1.616?s | 0.083?s | 6.97%  | 1.54x |
| BenchmarkJson | benchLastErrorInvalid | 0   | 1000 | 100 | 2,980,184b | 0.785?s | 0.861?s | 0.863?s | 1.132?s | 0.056?s | 6.54%  | 1.11x |
| BenchmarkJson | benchNullValid        | 0   | 1000 | 100 | 2,980,168b | 0.985?s | 1.124?s | 1.077?s | 1.731?s | 0.114?s | 10.15% | 1.45x |
| BenchmarkJson | benchNullInvalid      | 0   | 1000 | 100 | 2,980,184b | 0.714?s | 0.775?s | 0.759?s | 1.073?s | 0.049?s | 6.36%  | 1.00x |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+

Run Code Online (Sandbox Code Playgroud)

结论:检查 json 是否有效的最快方法是返回json_decode($json, true) !== null).


Ram*_*ami 8

简单的方法是检查json结果..

$result = @json_decode($json,true);
    if (is_array($result)) {
        echo 'JSON is valid';
    }else{
        echo 'JSON is not valid';
    }
Run Code Online (Sandbox Code Playgroud)


Lew*_*van 8

这样做:

function isJson($string) {
    $decoded = json_decode($string); // decode our JSON string
    if ( !is_object($decoded) && !is_array($decoded) ) {
        /*
        If our string doesn't produce an object or array
        it's invalid, so we should return false
        */
        return false;
    }
    /*
    If the following line resolves to true, then there was
    no error and our JSON is valid, so we return true.
    Otherwise it isn't, so we return false.
    */
    return (json_last_error() == JSON_ERROR_NONE);
}

if ( isJson($someJsonString) ) {
    echo "valid JSON";
} else {
    echo "not valid JSON";
}
Run Code Online (Sandbox Code Playgroud)


Ion*_*zan 7

虽然仍在开发中的 PHP 8.3 将配备新的内存高效json_validate()功能,但由于令人惊叹的Symfony Polyfill组件,您可以将其与旧版 PHP 版本(7.1 及更高版本)一起使用。

只需将以下包添加到您的项目中:

composer require symfony/polyfill-php83
Run Code Online (Sandbox Code Playgroud)

并在您的应用程序中使用它:

if (json_validate($data)) {
  // do sometihng
}
Run Code Online (Sandbox Code Playgroud)

通过这种方法,您可以在旧应用程序中使用新的 PHP 功能,并在将来迁移到 PHP 8.3,而无需更改任何代码,因为您的代码将自动使用可用的内置函数。


小智 6

GuzzleHttp:

/**
 * Wrapper for json_decode that throws when an error occurs.
 *
 * @param string $json    JSON data to parse
 * @param bool $assoc     When true, returned objects will be converted
 *                        into associative arrays.
 * @param int    $depth   User specified recursion depth.
 * @param int    $options Bitmask of JSON decode options.
 *
 * @return mixed
 * @throws \InvalidArgumentException if the JSON cannot be decoded.
 * @link http://www.php.net/manual/en/function.json-decode.php
 */
function json_decode($json, $assoc = false, $depth = 512, $options = 0)
{
    $data = \json_decode($json, $assoc, $depth, $options);
    if (JSON_ERROR_NONE !== json_last_error()) {
        throw new \InvalidArgumentException(
            'json_decode error: ' . json_last_error_msg());
    }

    return $data;
}

/**
 * Wrapper for JSON encoding that throws when an error occurs.
 *
 * @param mixed $value   The value being encoded
 * @param int    $options JSON encode option bitmask
 * @param int    $depth   Set the maximum depth. Must be greater than zero.
 *
 * @return string
 * @throws \InvalidArgumentException if the JSON cannot be encoded.
 * @link http://www.php.net/manual/en/function.json-encode.php
 */
function json_encode($value, $options = 0, $depth = 512)
{
    $json = \json_encode($value, $options, $depth);
    if (JSON_ERROR_NONE !== json_last_error()) {
        throw new \InvalidArgumentException(
            'json_encode error: ' . json_last_error_msg());
    }

    return $json;
}
Run Code Online (Sandbox Code Playgroud)


小智 6

//Tested thoroughly, Should do the job:
public static function is_json(string $json):bool
{
    json_decode($json);
    if (json_last_error() === JSON_ERROR_NONE) {
        return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)


jcm*_*ina 6

json_validate()函数的 RFC已实现,并将成为 PHP 8.3 的一部分

这种方法将是实现问题所要求的最快、最有效的方法。

github - 实现代码

rfc - json_validate()


Aha*_*Ali 5

早些时候我只是检查一个空值,实际上这是错误的.

    $data = "ahad";
    $r_data = json_decode($data);
    if($r_data){//json_decode will return null, which is the behavior we expect
        //success
    }
Run Code Online (Sandbox Code Playgroud)

上面的代码可以很好地处理字符串.但是,只要我提供号码,它就会崩溃.例如.

    $data = "1213145";
    $r_data = json_decode($data);

    if($r_data){//json_decode will return 1213145, which is the behavior we don't expect
        //success
    }
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,我所做的非常简单.

    $data = "ahad";
    $r_data = json_decode($data);

    if(($r_data != $data) && $r_data)
        print "Json success";
    else
        print "Json error";
Run Code Online (Sandbox Code Playgroud)


Ser*_*nko 5

我们需要检查传递的字符串是否不是数字,因为在这种情况下 json_decode 不会引发错误。

function isJson($str) {
    $result = false;
    if (!preg_match("/^\d+$/", trim($str))) {
        json_decode($str);
        $result = (json_last_error() == JSON_ERROR_NONE);
    }

    return $result;
}
Run Code Online (Sandbox Code Playgroud)


Phi*_*ipp 5

最快的方法是“可能解码”可能的 JSON 字符串

这真的是最快的方法吗?

如果你想解码复杂的对象或更大的数组,这是迄今为止最快的方法!

如果您的 json 字符串包含短值(如标量或只有 1-2 个属性的对象),那么此 SO 问题中的所有解决方案都具有类似的性能

这是我使用一些虚拟和真实JSON 值进行的性能比较:

PHP version: 7.4.12
1 | Duration: 1.5828 sec | 60,000 calls | json_last_error() == JSON_ERROR_NONE
2 | Duration: 1.5202 sec | 60,000 calls | is_object( json_decode() )
3 | Duration: 1.5400 sec | 60,000 calls | json_decode() && $res != $string
4 | Duration: 1.3536 sec | 60,000 calls | preg_match()
5 | Duration: 0.2261 sec | 60,000 calls | "maybe decode" approach
Run Code Online (Sandbox Code Playgroud)

最后一行是这个答案的代码,这是“也许解码”的方法。

这是性能比较脚本,您可以在那里看到我用于比较的测试数据:https : //gist.github.com/stracker-phil/6a80e6faedea8dab090b4bf6668ee461


“可能解码”逻辑/代码

在尝试解码 JSON 字符串之前,我们首先执行一些类型检查和字符串比较。这为我们提供了最佳性能,因为 json_decode() 可能很慢。

PHP version: 7.4.12
1 | Duration: 1.5828 sec | 60,000 calls | json_last_error() == JSON_ERROR_NONE
2 | Duration: 1.5202 sec | 60,000 calls | is_object( json_decode() )
3 | Duration: 1.5400 sec | 60,000 calls | json_decode() && $res != $string
4 | Duration: 1.3536 sec | 60,000 calls | preg_match()
5 | Duration: 0.2261 sec | 60,000 calls | "maybe decode" approach
Run Code Online (Sandbox Code Playgroud)

额外:使用此逻辑安全地对 JSON 进行双重解码

此函数使用相同的逻辑,但返回解码后的 JSON 对象原始值

我在递归解码复杂对象的解析器中使用此函数。某些属性可能已被较早的迭代解码。该函数识别出这一点,并且不会再次尝试对该值进行双重解码。

/**
 * Returns true, when the given parameter is a valid JSON string.
 */
function is_json( $value ) {
    // A non-string value can never be a JSON string.
    if ( ! is_string( $value ) ) { return false; }

    // Numeric strings are always valid JSON.
    if ( is_numeric( $value ) ) { return true; }

    // Any non-numeric JSON string must be longer than 2 characters.
    if ( strlen( $value ) < 2 ) { return false; }

    // "null" is valid JSON string.
    if ( 'null' === $value ) { return true; }

    // "true" and "false" are valid JSON strings.
    if ( 'true' === $value ) { return true; }
    if ( 'false' === $value ) { return false; }

    // Any other JSON string has to be wrapped in {}, [] or "".
    if ( '{' != $value[0] && '[' != $value[0] && '"' != $value[0] ) { return false; }

    // Note the last param (1), this limits the depth to the first level.
    $json_data = json_decode( $value, null, 1 );

    // When json_decode fails, it returns NULL.
    if ( is_null( $json_data ) ) { return false; }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

注意:在此 SO 问题中将非字符串传递给任何其他解决方案时,您将获得显着降低的性能+ 错误的返回值(甚至致命错误)。此代码是防弹且高性能的。

  • @EnigmaPlus 谢谢:) 是的,代码不是优雅的单行代码,但问题是找到**最快**的方法,而不是最优雅/最短的方法。`json_decode` 更短,但需要 PHP 初始化一个内部 JSON-Parser 实例,该实例非常复杂,并且比 8 个简单的 `if` 慢很多 (2认同)