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


385

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

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

是否有任何性能发烧友想改进此方法?


3
考虑只使用json_decode一次...,还要检查的输入和返回值json_decode

5
那么,答案是哪一个呢?
Farid Rn 2012年

8
这里的三元开关是冗余的。您的陈述式已评估为布尔值。
我曾经摔过一只熊。


接受刘易斯·多诺万(Lewis Donovan)的回答...工作正常
Poonam Bhatt

Answers:


573
function isJson($string) {
 json_decode($string);
 return (json_last_error() == JSON_ERROR_NONE);
}

19
似乎每个人都喜欢这个答案。有什么解释吗?
Kirk Ouimet

8
我相信PHP 5.3>是使用json_last_error功能所需要的
克里斯·哈里森

97
如果期望许多传入字符串为非JSON {,则检查string的第一个字符是否为,[或其他任何文字的第一个符号都可以极大地加快此速度。
Oleg V. Volkov 2012年

20
$ phone ='021234567'; var_dump(isJson($ phone)); 返回真不!它应该返回false。
vee 2014年

23
请注意,无论您将其指定为字符串还是真数字,此函数也将对任何数字返回真。6.5 = true, '300' = true, 9 = true因此,这可能是有效的JSON值,但是如果您只想使用{}或来检查有效的JSON字符串,则该函数的行为可能与预期的不同[]
BadHorsie 2014年

156

回答问题

该函数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
}

请注意,json_last_error仅PHP> = 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;
}

使用有效的JSON INPUT测试

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

有效输出

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

    [1] => stdClass Object
        (
            [user_id] => 14
            [username] => over
        )
)

使用无效的JSON测试

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

无效的输出

Syntax error, malformed JSON.

(PHP> = 5.2 && PHP <5.3.0)的附加说明

由于json_last_errorPHP 5.2不支持,因此您可以检查编码或解码是否返回boolean FALSE。这是一个例子

// decode the JSON data
$result = json_decode($json);
if ($result === FALSE) {
    // JSON is invalid
}

希望这会有所帮助。编码愉快!


精度不高:如果此json有效,但先前解码的无效,则您的代码将正常工作,因为:“ 返回上一次 JSON编码/解码期间发生的最后错误(如果有)。
Bruno

感谢@Madan,“ json_decode”验证对我来说证明我正在运行PHP 7.0。
Francis Rodrigues

当然json_decode可以只为假false返回false,所以((strlen($json) === 5) && ($json !== 'false'))还应该进行检查以避免出现这种情况?
MrMesees'7

@Bruno如果最后的解码没有错误,则json_last_error返回JSON_ERROR_NONE
安德里亚(Andrea)'18

81

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

if (is_object(json_decode($MyJSONArray))) 
{ 
    ... do something ...
}

该请求甚至不需要单独的功能。只需在json_decode周围包裹is_object并继续。似乎这种解决方案使人们投入了太多的思考。


@ RomanM.Kos需要明确的是,如果数组是一个简单数组,则is_array除了需要使用之外is_object,否则is_object对于编码为JSON的简单数组,将返回false。因此,@ ggutenberg在这种情况下是正确的。传递true参数以json_decode强制将对象作为数组返回。从理论上讲,您可以始终将解码强制为数组,然后只需检查即可is_array
userabuser 2014年

@userabuser如果我json_encode($array)使用简单的PHP数组,那么json_decode($str)我将接收对象,但不接收数组。json_decode($str, true)强制转换为数组。为什么在代码中使用复杂的字符串?检查一下,is_array(json_decode($str, true))稍后阅读时,您将了解已解码必须仅是一个数组。很难猜测is_object(json_decode($MyJSONArray))“哦,在这里我要检查解码的是数组还是不是数组?”
Roman M. Koss

@ RomanM.Kos不,那是不正确的, codepad.viper-7.com/OFrtsq-正如我所说,您始终可以强制json_decode返回一个数组以保存对对象和数组的检查,但是如果不这样做json_decode又该怎么办首先是一个简单的数组,您将收到一个解码返回的数组,而不是对象。JSON_FORCE_OBJECT如果要始终在传递简单数组的编码IF上强制对象,则必须使用。
userabuser 2014年

11
不赞成说: This request does not require a separate function even。严格来说,没有解决方案需要单独的功能。函数的重点不是使多行代码看起来像一行代码。该功能的要点是在您的应用程序中的所有地方都使JSON检查过程成为标准,以便不同的程序员(或者随着时间的推移同一个程序员)在程序流程的不同阶段不使用不同的检查过程。
cartbeforehorse 2014年

71

使用json_decode到“探针”它可能不是实际上是最快的方法。如果是深层嵌套的结构,则实例化许多数组对象以将它们扔掉会浪费内存和时间。

所以它可能是更快地使用preg_matchRFC4627的正则表达式确保有效性

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

在PHP中也一样:

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

但是,这里没有足够的性能爱好者来打扰基准测试。


11
完整的递归正则表达式可在此处验证JSON:stackoverflow.com/questions/2583472/regex-to-validate-json / ...-但事实证明,PHP json_decode始终比PCRE正则表达式快。(尽管它不是很优化,但没有发现综合测试,并且在Perl中的表现可能有所不同。)
mario

3
@vee是的,感谢您的来信。但是让我们[不正确地]保留在这里,所以实际上没有人在生产中使用它。
mario 2014年

1
@cartbeforehorse好的,谢谢。然后,我修复了PHP的双引号字符串上下文转义。
mario'7

1
@cartbeforehorse不是。主要是装修。只是字面反斜杠确实需要加倍转义。因为\r \n \t这很有意义,所以PHP不会对它们进行插值,而是让PCRE解释它们(仅/x模式需要)。其他事件并不严格需要它。但在所有字符串PHP上下文中仍然存在“反斜杠本身”。因此,可以认为它更精确。
mario'7

4
@mario好的,我知道了。因此,基本上,PHP在reg-exp引擎看到它之前就转义了反斜杠。就正则表达式引擎而言,字符串中反斜杠的数量是我们人类所看到的一半。 “就像reg-exp还不够复杂”
cartbeforehorse

39

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

function isJson($str) {
    $json = json_decode($str);
    return $json && $str != $json;
}

它拒绝仅包含数字,字符串或布尔值的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)

这是我想出的最短方法。


您可以将其放在PHPUnit测试用例中,而不是var_dump。否则,我既惊讶又高兴得知这是真的。
MrMesees'7

3
当这个方法行之有效时,为什么其他所有人都有如此漫长的答案呢?谢谢。
toddmo '18年

1
简单,可爱!并没有检查“最快的方法”或性能方面的建议,但是这个可以肯定地涵盖了我曾经检查过的所有情况。这是臭名昭著的谚语“不要用大锤砸破螺母”的经典示例。从程序员的角度来看,使代码保持简单,简短和易于理解总是更好的选择,性能还是简单性是该线程范围之外的另一个争论。
Fr0zenFyr

这是一个很巧妙的逻辑,但也请注意,对于空数组,它返回false。例如:var_dump(isJson('[]')); // bool(false)。根据有关布尔值的文档,这是因为PHP将零元素的数组评估为false。这是对返回声明进行调整的一个小修改;它对处理这种情况的解码输出执行相同的比较:return $json !== false && $str != $json;
j13k,

@ j13k相同的比较结果isJson('hello')为true,这不是有效的json。在这里故意选择松散比较。我没有针对空数组/对象情况的快速解决方案,除了一个丑陋的问题return $json == '[]' || ...
西里尔(Cyril)

21

我使用的最简单,最快的方法是:

$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

这是因为如果输入的字符串不是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.
}

在上面的函数中,如果它是有效的JSON,则将返回true。


3
json_decode('null') == NULL并且null是有效的JSON值。
zzzzBov

我已经在json.parser.online上测试了'null'是否为有效的json,但似乎它不是有效的json。而且json_decode()是用于验证json的php核心函数,因此我怀疑在我们的输出中会得到一些错误的结果。
Mohammad Mursaleen

与其信任某些未经验证的网站,不如考虑参考不同意的规范(第2页)。或者,JSON.parse('null')在您的开发控制台中尝试。
zzzzBov

19
function is_json($str){ 
    return json_decode($str) != null;
}

如果检测到无效编码,则http://tr.php.net/manual/zh-CN/function.json-decode.php返回值为null。


4
它还会为“ null”错误地返回null(这不是有效的JSON,但对于json_decode可能完全“有效”)。去搞清楚。

我认为这应该是:json_decode($str)!=null;否则应调用函数is_not_json
耀西

最好将该函数重命名为“ JSON以外的东西”!
lonesomeday

2
@ user166390,json_decode('null')根据规范为有效JSON,应返回的值null
zzzzBov

另请注意,使用此方法is_json('false')is_json('[]')false在未检查类型的情况下返回。我认为这种方法应该返回$str === null || json_decode($str) !== null
Antoine Pinsard,2015年

11

您必须验证输入内容,以确保传递的字符串不为空,并且实际上是字符串。空字符串不是有效的JSON。

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

我认为在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;
}

+1用于在实际环境中实际考虑问题。
cartbeforehorse 2014年

但是'0'不是有效的json ...我为什么要警惕?@Kzqai
更新

11

这样做:

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";
}

如其他答案所示,json_last_error()从我们上一个json_decode()返回任何错误。但是,在某些边缘用例中,仅此功能还不够全面。例如,如果您json_decode()使用整数(例如:123:)或没有空格或其他字符的数字字符串(例如:)"123",则该json_last_error()函数将不会捕获错误。

为了解决这个问题,我添加了一个额外的步骤来确保我们的结果 json_decode()是对象还是数组。如果不是,那么我们返回false

要查看实际效果,请查看以下两个示例:


"hello"是有效的JSON,它不是对象,也不是数组,json_last_error()就足够了
JoniJnm

1
json_last_error()4当您json_decode()输入字符串时,将返回错误代码"hello"。此处的示例:3v4l.org/lSsEo
Lewis Donovan

你的代码是错误的,hello是不是有效的JSON,不过"hello"3v4l.org/OEJrQ
JoniJnm


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;
}

5

之前我只是检查一个空值,实际上这是错误的。

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

上面的代码对字符串可以正常工作。但是,一旦我提供号码,它就会分手。

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

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

要解决它,我所做的事情非常简单。

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

    if(($r_data != $data) && $r_data)
        print "Json success";
    else
        print "Json error";

不错的解决方案。很好地处理打字问题!
Chaoix

5
//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;
}

4

另一种简单的方法

function is_json($str)
{
    return is_array(json_decode($str,true));
}

1
这是不对的。任何PHP类型都可以编码为JSON,例如对象,字符串等,并且json_decode函数应返回它们。仅当您始终在解码数组且没有其他变量类型时才如此。
Chaoix

@Chaoix using json_decode($str,true)使它可以将对象转换为数组,因此它将通过is_array检查。您可以对字符串,整数等进行更正。
Paul Phillips'Mar

我明白了您对json_encode上第二个参数的含义。我仍然认为@Ahad Ali的解决方案在类型上要好得多,并且在算法中只执行一次json_decode。
Chaoix

4

我们需要检查传递的字符串是否不是数字,因为在这种情况下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;
}

3

我已经尝试了其中一些解决方案,但没有任何工作对我有用。我尝试这个简单的事情:

$isJson = json_decode($myJSON);

if ($isJson instanceof \stdClass || is_array($isJson)) {
   echo("it's JSON confirmed");
} else {
   echo("nope");
}

我认为这是一个很好的解决方案,因为不带第二个参数的JSON解码给出了一个对象。

编辑:如果您知道输入的内容,则可以根据需要调整此代码。就我而言,我知道我有一个以“ {”开头的Json,所以我不需要检查它是否为数组。


您的JSON可能只是一个数组,在这种情况下,它将是一个数组,而不是stdClass $ foo =“ [1,1,2,3]”; var_dump(json_decode($ foo)); => array(4){[0] => int(1)[1] => int(1)[2] => int(2)[3] => int(3)}
Misha Nasledov

3

将PHPBench与以下类一起使用,可获得以下结果:

<?php

declare(strict_types=1);

/**
 * Benchmark doctrine persistent collection count method vs sizeof toArray
 * Revs is the number of times you want the benchmark to run
 * @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);
    }
}
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 |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+

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


非常好:)我佩服您
Mahdi

3

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

function is_JSON($string) {

  $String_Is_JSON = (is_null(json_decode($string, TRUE))) ? FALSE : TRUE;

  return $String_Is_JSON;
}

2

我不知道我的解决方案的性能或优雅程度,但这是我正在使用的方法:

if (preg_match('/^[\[\{]\"/', $string)) {
    $aJson = json_decode($string, true);
    if (!is_null($aJson)) {
       ... do stuff here ...
    }
}

由于我所有的JSON编码字符串都以{“开头,因此足以使用RegEx进行测试。我对RegEx一点都不流利,因此可能有更好的方法来做到这一点。另外:strpos()可能更快。

只是想让我的钱值得。

PS刚刚将RegEx字符串更新为/^[\[\{]\"/,还可以找到JSON数组字符串。因此,它现在在字符串的开头查找[“或{”。


2

应该是这样的:

 function isJson($string)
 {
    // 1. Speed up the checking & prevent exception throw when non string is passed
    if (is_numeric($string) ||
        !is_string($string) ||
        !$string) {
        return false;
    }

    $cleaned_str = trim($string);
    if (!$cleaned_str || !in_array($cleaned_str[0], ['{', '['])) {
        return false;
    }

    // 2. Actual checking
    $str = json_decode($string);
    return (json_last_error() == JSON_ERROR_NONE) && $str && $str != $string;
}

单元测试

public function testIsJson()
{
    $non_json_values = [
        "12",
        0,
        1,
        12,
        -1,
        '',
        null,
        0.1,
        '.',
        "''",
        true,
        false,
        [],
        '""',
        '[]',
        '   {',
        '   [',
    ];

   $json_values = [
        '{}',
        '{"foo": "bar"}',
        '[{}]',
        '  {}',
        ' {}  '
    ];

   foreach ($non_json_values as $non_json_value) {
        $is_json = isJson($non_json_value);
        $this->assertFalse($is_json);
    }

    foreach ($json_values as $json_value) {
        $is_json = isJson($json_value);
        $this->assertTrue($is_json);
    }
}

我喜欢您要检查它是否是字符串。与第一个解决方案结合使用可很好地避免ErrorException字符串是数组还是对象。
sykez

1

扩展此答案如何处理:

<?php

    $json = '[{"user_id":13,"username":"stack"},{"user_id":14,"username":"over"}]';
    //$json = '12';

    function isJson($string) {
        json_decode($string);
        if(json_last_error() == JSON_ERROR_NONE) {
            if(substr($string,0,1) == '[' && substr($string,-1) == ']') { return TRUE; }
            else if(substr($string,0,1) == '{' && substr($string,-1) == '}') { return TRUE; }
            else { return FALSE; }
        }
    }

    echo isJson($json);
?>

1
如果在子字符串检查中发现错误,是否应该在执行解码之前进行子字符串检查以节省时间?我可以想象4个子字符串检查会比json_decode更快,但是如果有人可以用这个假设支持我,我将不胜感激。
标记

那是票价论点。我不知道所涉及的处理时间,但是如果更快,那么可以。
七世界

1

嗨,这是我库中的一小段代码,在这种情况下,我只是检查数据是否为json,如果解码正确,则将其返回,请注意性能的substr用法(我还没有看到任何json文件没有开始通过{或[

$input=trim($input);
if ((substr($input, 0, 1) == '{' && substr($input, -1) == '}') or (substr($input, 0, 1) == '[' && substr($input, -1) == ']')) {
    $output = json_decode($input, 1);
    if (in_array(gettype($output),['object','array'])) {
        #then it's definitely JSON
    }
}

这个问题已经发布了34个答案,其中许多还支持(错误的)信念,即JSON必须表示数组或对象。这个答案与其他3打答案有什么不同吗?
miken32 '18

1

我的另一个建议:)

function isJson(string $string) {
  return ($result = json_decode($string, true)) ? $result : $string;
}

0

自定义功能

function custom_json_decode(&$contents=NULL, $normalize_contents=true, $force_array=true){

    //---------------decode contents---------------------

    $decoded_contents=NULL;

    if(is_string($contents)){

        $decoded_contents=json_decode($contents,$force_array);

    }

    //---------------normalize contents---------------------

    if($normalize_contents===true){

        if(is_string($decoded_contents)){

            if($decoded_contents==='NULL'||$decoded_contents==='null'){

                $contents=NULL;
            }
            elseif($decoded_contents==='FALSE'||$decoded_contents==='false'){

                $contents=false;
            }
        }
        elseif(!is_null($decoded_contents)){

            $contents=$decoded_contents;
        }
    }
    else{

        //---------------validation contents---------------------

        $contents=$decoded_contents;
    }

    return $contents;
}

案例

$none_json_str='hello';

//------------decoding a none json str---------------

$contents=custom_json_decode($none_json_str); // returns 'hello'

//------------checking a none json str---------------

custom_json_decode($none_json_str,false);

$valid_json=false;

if(!is_null($none_json_str)){

    $valid_json=true;

}

资源资源

https://gist.github.com/rafasashi/93d06bae83cc1a1f440b


0

如果需要成功的解码数据,则可以使用与PHP 5.2兼容的最新功能:

function try_json_decode( $json, & $success = null ){
  // non-strings may cause warnings
  if( !is_string( $json )){
    $success = false;
    return $json;
  }

  $data = json_decode( $json );

  // output arg
  $success =

    // non-null data: success!
    $data !==  null  ||

    // null data from 'null' json: success!
    $json === 'null' ||

    // null data from '  null  ' json padded with whitespaces: success!
    preg_match('/^\s*null\s*$/', $json );

  // return decoded or original data
  return $success ? $data : $json;
}

用法:

$json_or_not = ...;

$data = try_json_decode( $json_or_not, $success );

if( $success )
     process_data( $data );
else what_the_hell_is_it( $data );

一些测试:

var_dump( try_json_decode( array(), $success ), $success );
// ret = array(0){}, $success == bool(false)

var_dump( try_json_decode( 123, $success ), $success );
// ret = int(123), $success == bool(false)

var_dump( try_json_decode('      ', $success ), $success );
// ret = string(6) "      ", $success == bool(false)

var_dump( try_json_decode( null, $success ), $success );
// ret = NULL, $success == bool(false)

var_dump( try_json_decode('null', $success ), $success );
// ret = NULL, $success == bool(true)

var_dump( try_json_decode('  null  ', $success ), $success );
// ret = NULL, $success == bool(true)

var_dump( try_json_decode('  true  ', $success ), $success );
// ret = bool(true), $success == bool(true)

var_dump( try_json_decode('  "hello"  ', $success ), $success );
// ret = string(5) "hello", $success == bool(true)

var_dump( try_json_decode('  {"a":123}  ', $success ), $success );
// ret = object(stdClass)#2 (1) { ["a"]=> int(123) }, $success == bool(true)

0
function is_json($input) {

    $input = trim($input);

    if (substr($input,0,1)!='{' OR substr($input,-1,1)!='}')
        return false;

    return is_array(@json_decode($input, true));
}

2
@用于调试(隐藏错误),但绝对不建议使用
aswzen 2015年

0

对henrik的答案进行了简单的修改,即可接触到大多数所需的可能性。

(包括“ {}和[]”)

function isValidJson($string) {
    json_decode($string);
    if(json_last_error() == JSON_ERROR_NONE) {

        if( $string[0] == "{" || $string[0] == "[" ) { 
            $first = $string [0];

            if( substr($string, -1) == "}" || substr($string, -1) == "]" ) {
                $last = substr($string, -1);

                if($first == "{" && $last == "}"){
                    return true;
                }

                if($first == "[" && $last == "]"){
                    return true;
                }

                return false;

            }
            return false;
        }

        return false;
    }

    return false;

}

0

以最快的方式也许解码可能JSON对象到PHP对象/数组:

/**
 * If $value is a JSON encoded object or array it will be decoded 
 * and returned.
 * If $value is not JSON format, then it will be returned unmodified.
 */
function get_data( $value ) {
    if ( ! is_string( $value ) ) { return $value; }
    if ( strlen( $value ) < 2 ) { return $value; }
    if ( '{' != $value[0] && '[' != $value[0] ) { return $value; }

    $json_data = json_decode( $value );
    if ( ! $json_data ) { return $value; }
    return $json_data;
}

0

这是我创建的一个高性能且简单的函数(在使用前使用基本的字符串验证 json_decode用于较大的字符串):

function isJson($string) {
    $response = false;

    if (
        is_string($string) &&
        ($string = trim($string)) &&
        ($stringLength = strlen($string)) &&
        (
            (
                stripos($string, '{') === 0 &&
                (stripos($string, '}', -1) + 1) === $stringLength
            ) ||
            (
                stripos($string, '[{') === 0 &&
                (stripos($string, '}]', -1) + 2) === $stringLength
            )
        ) &&
        ($decodedString = json_decode($string, true)) &&
        is_array($decodedString)
    ) {
        $response = true;
    }

    return $response;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.