A maneira mais rápida de verificar se uma string é JSON em PHP?

385

Eu preciso de um método muito, muito rápido de verificar se uma string é JSON ou não. Eu sinto que esta não é a melhor maneira:

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

Algum entusiasta de desempenho por aí quer melhorar esse método?

Kirk Ouimet
fonte
3
Considere usar apenas json_decodeuma vez ... também, verifique os valores de entrada e retorno de json_decode.
5
Então, qual é a resposta?
Farid Rn
8
A chave ternária aqui é redundante. Sua declaração já é avaliada como booleana.
Lutei com um urso uma vez.
Bem aceitar a resposta de Lewis Donovan ... ele está trabalhando
Poonam Bhatt

Respostas:

574
function isJson($string) {
 json_decode($string);
 return (json_last_error() == JSON_ERROR_NONE);
}
Henrik P. Hessel
fonte
19
Parece que todo mundo está amando essa resposta. Alguma explicação porque?
Kirk Ouimet
8
Acredito PHP 5.3> é necessário para utilizar a função json_last_error
Chris Harrison
97
A verificação do primeiro caractere da cadeia de caracteres {, [ou o primeiro símbolo de qualquer outro literal, pode potencialmente acelerar muito este quando se espera que muitas das cadeias de entrada não sejam JSON.
Oleg V. Volkov
20
$ phone = '021234567'; var_dump (isJson ($ phone)); retornar verdadeiro não! deve retornar falso.
vee
23
Cuidado, essa função também retornará true para qualquer número, se você a especificar como uma string ou um número verdadeiro. 6.5 = true, '300' = true, 9 = trueetc. Portanto, esse pode ser um valor JSON válido, mas a função pode não se comportar conforme o esperado, se você deseja verificar apenas as strings JSON válidas com {}or [];
BadHorsie 25/02
156

Responda a pergunta

A função json_last_errorretorna o último erro ocorrido durante a codificação e decodificação JSON. Portanto, a maneira mais rápida de verificar o JSON válido é

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

Observe que isso json_last_erroré suportado apenas no PHP> = 5.3.0.

Programa completo para verificar o erro exato

É sempre bom saber o erro exato durante o tempo de desenvolvimento. Aqui está o programa completo para verificar o erro exato com base nos documentos do 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;
}

Testando com JSON INPUT Válido

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

SAÍDA válida

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

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

Testando com JSON inválido

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

SAÍDA inválida

Syntax error, malformed JSON.

Nota extra para (PHP> = 5.2 e& PHP <5.3.0)

Como json_last_errornão é suportado no PHP 5.2, você pode verificar se a codificação ou decodificação retorna booleano FALSE. Aqui está um exemplo

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

Espero que isso seja útil. Feliz codificação!

Madan Sapkota
fonte
Pouca precisão: se este json for válido, mas um decodificado anterior for inválido, seu código funcionará corretamente, porque: " Retorna o último erro (se houver) ocorrido durante a última codificação / decodificação JSON. "
Bruno
Obrigado @ Madan, a verificação "json_decode" resolveu para mim que eu estava executando o PHP 7.0.
Francis Rodrigues
Certamente json_decode poderia simplesmente retornar false para o literal false, então uma verificação ((strlen($json) === 5) && ($json !== 'false'))também deve ser realizada para evitar essa vantagem?
MrMesees
@Bruno Se a última decodificação funcionar sem erros, ela json_last_errorretornará JSON_ERROR_NONE.
187 Andrea Andrea
80

Tudo o que você realmente precisa fazer é isso ...

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

Esta solicitação não requer uma função separada mesmo. Apenas envolva is_object em json_decode e siga em frente. Parece que esta solução faz com que as pessoas pensem demais nela.

user1653711
fonte
11
@ RomanM.Kos Apenas para esclarecer, se a matriz for uma matriz simples, você precisará usar is_arrayalém de is_object, caso contrário is_object, retornará false para matrizes simples codificadas como JSON. Então, @ggutenberg está certo neste caso. Passar o argumento verdadeiro para json_decodeforça um objeto a ser retornado como uma matriz. Em teoria, você sempre pode forçar a decodificação para uma matriz e apenas verificar se is_arrayisso deve funcionar.
userabuser
@userabuser Se for json_encode($array)para uma matriz PHP simples, json_decode($str)receberei o objeto, mas não a matriz. json_decode($str, true)obriga a converter em matriz. Por que seqüência complicada no seu código? Verifique is_array(json_decode($str, true))e, algum tempo depois, quando o ler, entenderá que o decodificado deve ser apenas uma matriz. Muito mais difícil de adivinhar is_object(json_decode($MyJSONArray))"Oh, aqui estou verificando se um decodificado é uma matriz ou não?"
Roman M. Koss
@ RomanM.Kos Não, isso não está correto, codepad.viper-7.com/OFrtsq - como eu disse, você sempre pode forçar json_decodea retornar uma matriz para poupar a verificação de objeto e matriz, mas se você não o fizer, e você o json_decodeque era uma matriz simples para começar, você receberá uma matriz em troca da decodificação, não um objeto. Você deve usar JSON_FORCE_OBJECTse quiser sempre forçar um objeto a codificar se passar uma matriz simples.
userabuser
11
Downvote para dizer: This request does not require a separate function even. A rigor, nenhuma solução requer uma função separada. O objetivo de uma função não é fazer com que várias linhas de código se pareçam com uma linha de código. O objetivo da função é tornar o processo de verificação JSON padrão em qualquer lugar do seu aplicativo, para que diferentes programadores (ou o mesmo programador ao longo do tempo) não usem procedimentos de verificação diferentes em diferentes estágios do fluxo do programa.
cartbeforehorse
71

Usando json_decode para "sondar" pode não ser o caminho mais rápido. Se for uma estrutura profundamente aninhada, instanciar muitos objetos de matrizes para jogá-los fora é um desperdício de memória e tempo.

Portanto, pode ser mais rápido usar preg_matcho regex RFC4627 para garantir também a validade :

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

O mesmo no PHP:

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

Um entusiasta do desempenho não é suficiente para se preocupar com benchmarks aqui, no entanto.

mario
fonte
11
Regex recursivo completo para verificar o JSON aqui: stackoverflow.com/questions/2583472/regex-to-validate-json/… - Mas acontece que PHPs json_decodeé sempre mais rápido que um regex PCRE. (Embora não seja muito otimizado, há testes sintéticos encontrados, e pode se comportar de forma diferente em Perl ..)
mario
3
@vee Sim, obrigado pela nota. Mas vamos mantê-lo aqui [incorretamente], para que ninguém realmente use isso na produção.
mario
11
@cartbeforehorse Ok, obrigado. Corrigi o contexto de escape de aspas saudáveis ​​para PHPs, com aspas duplas.
mario
11
@cartbeforehorse Isso não acontece. Principalmente decoração. É apenas a barra invertida literal que de fato requer duplamente escape. Pois \r \n \tfaz sentido que o PHP não os interpole, mas permita que o PCRE os interprete (apenas foi necessário para o /xmodo). As outras ocorrências não precisam disso estritamente; ainda assim "a barra invertida se escapa" em todos os contextos de string do PHP. Portanto, pode-se considerar mais exato.
mario
4
@ Mario Ok, entendo. Então, basicamente, o PHP escapa as barras invertidas antes que o mecanismo reg-exp o veja. No que diz respeito ao mecanismo reg-exp, há metade do número de barras invertidas na string como o que nós humanos vemos. "Como reg-exp já não era complicado o suficiente"
cartbeforehorse
39

Isso retornará true se sua string representar uma matriz ou objeto json :

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

Ele rejeita as strings json que contêm apenas um número, string ou booleano, embora essas strings sejam json tecnicamente válidas.

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)

É a maneira mais curta que eu consigo.

Cyril
fonte
Em vez de var_dump, você pode colocar isso em um caso de teste do PHPUnit. Caso contrário, fico surpreso e feliz em saber que é verdade.
MrMesees
3
Por que todo mundo tem respostas tão longas quando isso funciona muito bem? Obrigado.
toddmo
11
Simplesmente adorável! Não verifiquei o "caminho mais rápido" ou o desempenho, mas este certamente cobre todos os casos que eu já verifiquei. Este é um exemplo clássico do infame provérbio "Não use marreta para quebrar uma noz" . Do ponto de vista do programador, é sempre melhor manter o código simples, curto e fácil de entender, desempenho versus simplicidade é outro debate fora do escopo desse segmento.
Fr0zenFyr
Este é um pouco de lógica, mas também observe que ele retorna false para matrizes vazias. Por exemplo: var_dump(isJson('[]')); // bool(false). De acordo com a documentação sobre booleanos, isso ocorre porque o PHP avalia matrizes com zero elementos como falsos. Aqui está uma pequena alteração para ajustar a declaração de retorno; ele executa uma comparação idêntica na saída decodificada que lida com este caso:return $json !== false && $str != $json;
j13k 11/11/1919
@ j13k A comparação idêntica é avaliada isJson('hello')como verdadeira, o que não é válido json. A comparação frouxa é escolhida de propósito aqui. Eu não tenho uma solução rápida para a situação Array / objeto vazio, exceto um feioreturn $json == '[]' || ...
Cyril
21

A maneira mais simples e rápida que eu uso é seguir;

$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

Isso ocorre porque json_decode () retorna NULL se a sequência inserida não for json ou json inválido.


Função simples para validar JSON

Se você precisar validar seu JSON em vários locais, sempre poderá usar a seguinte função.

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

Na função acima, você retornará true se for um JSON válido.

Mohammad Mursaleen
fonte
3
json_decode('null') == NULLe nullé um valor JSON válido.
ZzzzBov 8/15/15
Eu testei se 'null' é válido json em json.parser.online, mas parece que não é válido json. E json_decode () é a função principal do php para validar o json, então duvido que obtenha algum resultado falso em nossa saída.
Mohammad Mursaleen
Em vez de confiar em algum site não verificado, considere consultar as especificações, o que não concorda (página 2) . Como alternativa, tente JSON.parse('null')no seu console de desenvolvimento.
ZzzzBov 24/05
19
function is_json($str){ 
    return json_decode($str) != null;
}

O valor de retorno http://tr.php.net/manual/en/function.json-decode.php é nulo quando a codificação inválida é detectada.

AhmetB - Google
fonte
4
Ele também retornará indevidamente nulo para "nulo" (que não é válido JSON, mas pode ser totalmente "válido" para json_decode caso contrário). Vai saber.
Eu acho que json_decode($str)!=null;deveria ser : ou então a função deve ser chamada is_not_json.
Yoshi
Essa função seria melhor renomeada "é algo diferente de JSON"!
Loneomeday
2
@ user166390, json_decode('null')é JSON válido de acordo com a especificação e deve retornar o valor de null.
zzzzBov
Observe também que com esse método is_json('false')e is_json('[]')retornará falsecomo o tipo não está marcado. Eu acho que esse método deveria retornar$str === null || json_decode($str) !== null .
Antoine Pinsard
11

Você deve validar sua entrada para garantir que a sequência que você passa não esteja vazia e seja, de fato, uma sequência. Uma cadeia vazia não é JSON válida.

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

Eu acho que no PHP é mais importante determinar se o objeto JSON ainda tem dados, porque para usar os dados que você precisará chamar json_encode()or json_decode(). Sugiro negar objetos JSON vazios para que você não esteja executando codificações e decodificações desnecessárias em dados vazios.

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;
}
cheio
fonte
+1 por realmente pensar sobre o problema em um contexto do mundo real.
cartbeforehorse
Mas '0'não é válido json ... por que eu seria cauteloso? @Kzqai
upful
11

Isso fará isso:

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

Como mostrado em outras respostas, json_last_error()retorna qualquer erro do nosso último json_decode (). No entanto, existem alguns casos de uso de borda em que essa função sozinha não é abrangente o suficiente. Por exemplo, se você é json_decode()um número inteiro (por exemplo:) 123ou uma sequência de números sem espaços ou outros caracteres (por exemplo:"123" :), a json_last_error()função não detectará um erro.

Para combater isso, adicionei uma etapa extra que garante que o resultado da nossa json_decode()seja um objeto ou uma matriz. Se não for, então retornamosfalse .

Para ver isso em ação, verifique estes dois exemplos:

Lewis Donovan
fonte
"hello"é um JSON válido, e não é um objeto nem um array, json_last_error()é suficiente
JoniJnm
11
json_last_error()retorna o código de erro 4quando você json_decode()a string "hello". Exemplo aqui: 3v4l.org/lSsEo
Lewis Donovan
Seu código está incorreto, hellonão é um JSON válido, mas "hello"é 3v4l.org/OEJrQ
JoniJnm
9

O método fácil é verificar o resultado do json.

$result = @json_decode($json,true);
    if (is_array($result)) {
        echo 'JSON is valid';
    }else{
        echo 'JSON is not valid';
    }
Rameez Rami
fonte
6

em 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;
}
Parsa
fonte
5

No início eu estava apenas verificando um valor nulo, que estava errado na verdade.

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

O trecho de código acima funciona bem com seqüências de caracteres. No entanto, assim que eu forneço o número, ele se divide. Por exemplo.

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

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

Para corrigi-lo, o que eu fiz foi muito simples.

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

    if(($r_data != $data) && $r_data)
        print "Json success";
    else
        print "Json error";
Ahad Ali
fonte
Ótima solução. Lida muito bem com o problema de digitação!
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;
}
PM7Temp
fonte
4

Outra maneira simples

function is_json($str)
{
    return is_array(json_decode($str,true));
}
h0mayun
fonte
11
Isto não está correto. Qualquer tipo de PHP pode ser codificado em JSON, como objetos, seqüências de caracteres, etc, e a função json_decode deverá devolvê-los. Isso só é verdade se você estiver sempre decodificando matrizes e nenhum outro tipo de variável.
Chaoix
O @Chaoix usando json_decode($str,true)faz com que ele converta objetos em matrizes para que passe na verificação is_array. Você corrige sobre strings, números inteiros, etc.
Paul Phillips
Eu vejo o que você quer dizer sobre o segundo parâmetro em json_encode. Ainda acho que a solução do @Ahad Ali é muito melhor em termos de digitação e apenas executando um json_decode uma vez em seus algoritmos.
Chaoix 26/03/2015
4

Precisamos verificar se a sequência passada não é numérica porque, neste caso, json_decode não gera erro.

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

    return $result;
}
Sergey Onishchenko
fonte
4

Encontrei essa pergunta depois de encontrar algo semelhante em meu trabalho, ontem. Minha solução no final foi um híbrido de algumas das abordagens acima:

function is_JSON($string) {

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

  return $String_Is_JSON;
}
Rounin
fonte
3

Eu tentei algumas dessas soluções, mas nada estava funcionando para mim. Eu tento essa coisa simples:

$isJson = json_decode($myJSON);

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

Eu acho que é uma ótima solução, já que o JSON decodifica sem o segundo parâmetro dar um objeto.

EDIT: Se você souber qual será a entrada, poderá adaptar esse código às suas necessidades. No meu caso, eu sei que tenho um Json que começa com "{", então não preciso verificar se é um array.

Greco Jonathan
fonte
Seu JSON poderia ser apenas uma matriz; nesse caso, seria uma matriz em vez de em vez de stdClass $ foo = "[1, 1, 2, 3]"; var_dump (json_decode ($ foo)); => matriz (4) {[0] => int (1) [1] => int (1) [2] => int (2) [3] => int (3)}
Misha Nasledov
3

Usando o PHPBench com a seguinte classe, os resultados abaixo foram alcançados:

<?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 |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+

Conclusão: A maneira mais rápida de verificar se o json é válido é retornar json_decode($json, true) !== null).

Matthew Anderson
fonte
muito bom :) eu te admiro
Mahdi
2

Não sei o desempenho ou a elegância da minha solução, mas é o que estou usando:

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

Como todas as minhas strings codificadas em JSON começam com {"basta testar isso com um RegEx. Eu não sou fluente com o RegEx, portanto pode haver uma maneira melhor de fazer isso. Além disso, strpos () pode ser mais rápido.

Apenas tentando ceder meu valor de tuppence.

PS: Atualizei a string RegEx /^[\[\{]\"/para também encontrar as strings da matriz JSON. Portanto, agora ele procura por ["ou {" no início da string.

maxpower9000
fonte
2

Deve ser algo como isto:

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

Teste de unidade

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);
    }
}
Tinh Dang
fonte
Eu gosto que você esteja verificando se é uma string. Combina bem com a primeira solução para evitar ErrorExceptionse a string é matriz ou objeto.
sykez 03/01
1

Expandindo esta resposta Que tal o seguinte:

<?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);
?>
Sevenearths
fonte
11
A verificação de substring não deve ser feita antes de executar a decodificação para economizar tempo se o erro for encontrado nessa verificação? Eu imaginaria que quatro verificações de substring seriam mais rápidas que um json_decode, mas se alguém pudesse me apoiar com essa suposição, agradeceria qualquer reflexão sobre isso.
Mark
Esse é um argumento de tarifa. Não sei o tempo de processamento envolvido, mas se for mais rápido, sim.
Sevenearths 17/08/2015
1

Olá, aqui está um pequeno trecho da minha biblioteca. Nesta primeira condição, estou apenas verificando se os dados são json e, em seguida, devolvemos se forem decodificados corretamente. por {ou [

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

Foram postadas 34 respostas para esta pergunta, muitas das quais também subscrevem a crença (equivocada) de que o JSON deve representar uma matriz ou um objeto. Esta resposta está fazendo algo diferente das outras 3 dúzias de respostas?
precisa saber é o seguinte

1

Outra sugestão minha :)

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

0

A função personalizada

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

Estojos

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

}

Recursos

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


0

Função recém-criada para compatibilidade com o PHP 5.2, se você precisar dos dados decodificados com êxito:

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

Uso:

$json_or_not = ...;

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

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

Alguns testes:

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
@ Uso para depurar (esconder um erro), mas é absolutamente não recomendado
aswzen

0

Uma modificação simples da resposta de henrik para tocar nas possibilidades mais necessárias.

(incluindo "{} e []")

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;

}

fonte
0

A maneira mais rápida de talvez decodificar um possível objeto JSON para um objeto / matriz 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;
}
Philipp
fonte
0

Aqui está uma função simples e de desempenho que eu criei (que usa a validação básica de strings antes de usar json_decodepara strings maiores):

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

fonte