Der schnellste Weg, um zu überprüfen, ob eine Zeichenfolge JSON in PHP ist?


385

Ich brauche eine sehr, sehr schnelle Methode, um zu überprüfen, ob eine Zeichenfolge JSON ist oder nicht. Ich denke, das ist nicht der beste Weg:

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

Möchten Performance-Enthusiasten diese Methode verbessern?


3
Erwägen Sie, nur json_decodeeinmal zu verwenden ... Überprüfen Sie auch die Eingabe- und Rückgabewerte von json_decode.

5
Also, welches ist die Antwort?
Farid Rn

8
Der ternäre Schalter ist hier redundant. Ihre Anweisung wird bereits als Boolescher Wert ausgewertet.
Ich habe einmal mit einem Bären gerungen.


Akzeptiere die Antwort von Lewis Donovan ... es funktioniert gut
Poonam Bhatt

Antworten:


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

19
Sieht so aus, als ob jeder diese Antwort liebt. Irgendeine Erklärung warum?
Kirk Ouimet

8
Ich glaube, PHP 5.3> wird benötigt, um die Funktion json_last_error zu verwenden
Chris Harrison

97
Überprüfen erste Zeichen der Zeichenfolge für {, [oder erstes Symbol einer anderen wörtlichen kann potenziell beschleunigen stark diese ein, wenn viele der eingehenden Strings erwarten nicht-JSON zu sein.
Oleg V. Volkov

20
$ phone = '021234567'; var_dump (isJson ($ phone)); gib wahr nein zurück! es sollte false zurückgeben.
Vee

23
Beachten Sie, dass diese Funktion auch für jede Zahl true zurückgibt, unabhängig davon, ob Sie sie als Zeichenfolge oder als wahre Zahl angeben. 6.5 = true, '300' = true, 9 = trueusw. Dies ist möglicherweise ein gültiger JSON-Wert, aber die Funktion verhält sich möglicherweise nicht wie erwartet, wenn Sie nur nach gültigen JSON-Zeichenfolgen mit {}oder suchen möchten [].
BadHorsie

156

Antwort auf die Frage

Die Funktion json_last_errorgibt den letzten Fehler zurück, der während der JSON-Codierung und -Decodierung aufgetreten ist. Der schnellste Weg, um den gültigen JSON zu überprüfen, ist

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

Beachten Sie, dass json_last_errordies nur in PHP> = 5.3.0 unterstützt wird.

Vollständiges Programm zur Überprüfung des genauen FEHLERS

Es ist immer gut, den genauen Fehler während der Entwicklungszeit zu kennen. Hier ist ein vollständiges Programm, um den genauen Fehler basierend auf PHP-Dokumenten zu überprüfen.

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

Testen mit gültigem JSON INPUT

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

Gültiger AUSGANG

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

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

Testen mit ungültigem JSON

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

Ungültige AUSGABE

Syntax error, malformed JSON.

Zusätzlicher Hinweis für (PHP> = 5.2 && PHP <5.3.0)

Da json_last_errordies in PHP 5.2 nicht unterstützt wird, können Sie überprüfen, ob die Codierung oder Decodierung boolesch ist FALSE. Hier ist ein Beispiel

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

Hoffe das ist hilfreich. Viel Spaß beim Codieren!


Geringe Genauigkeit: Wenn dieser JSON gültig ist, ein zuvor dekodierter jedoch ungültig ist, funktioniert Ihr Code ordnungsgemäß, da: " Gibt den letzten Fehler (falls vorhanden) zurück, der während der letzten JSON-Codierung / -Decodierung aufgetreten ist . "
Bruno

Vielen Dank an @Madan, die Bestätigung "json_decode" hat mich gelöst, dass ich PHP 7.0 verwende.
Francis Rodrigues

Sicherlich könnte json_decode nur false für das Literal false zurückgeben, daher ((strlen($json) === 5) && ($json !== 'false'))sollte auch eine Überprüfung durchgeführt werden, um diese Kante zu vermeiden.
MrMesees

@Bruno Wenn die letzte Dekodierung fehlerfrei funktioniert, wird json_last_errorzurückgegeben JSON_ERROR_NONE.
Andrea

80

Alles was Sie wirklich tun müssen ist dies ...

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

Diese Anfrage erfordert nicht einmal eine separate Funktion. Wickeln Sie einfach is_object um json_decode und fahren Sie fort. Anscheinend haben die Leute bei dieser Lösung viel zu viel darüber nachgedacht.


1
@ RomanM.Kos Nur um klar zu sein, wenn das Array ein einfaches Array ist, müssen Sie es is_arrayzusätzlich zu verwenden is_object, andernfalls is_objectwird false für einfache Arrays zurückgegeben, die als JSON codiert sind. Also @ggutenberg ist in diesem Fall richtig. Wenn Sie das Argument true an übergeben json_decode, wird die Rückgabe eines Objekts als Array erzwungen. Sie könnten theoretisch immer die Dekodierung in ein Array erzwingen und nur überprüfen is_array, ob dies funktionieren sollte.
Userabuser

@userabuser Wenn ich json_encode($array)für einfaches PHP-Array, und dann werde ich json_decode($str)Objekt erhalten, aber kein Array. json_decode($str, true)zwingt zur Umwandlung in ein Array. Warum komplizierte Zeichenfolge in Ihrem Code? Suchen Sie nach is_array(json_decode($str, true))und einige Zeit später, wenn Sie es lesen, werden Sie verstehen, dass dekodiert nur ein Array sein darf. Viel schwerer zu erraten is_object(json_decode($MyJSONArray))"Oh, hier überprüfe ich, ob ein Array dekodiert ist oder nicht?"
Roman M. Koss

@ RomanM.Kos Nein, das ist nicht korrekt, codepad.viper-7.com/OFrtsq - wie gesagt, Sie können jederzeit json_decodedie Rückgabe eines Arrays erzwingen , um zu sparen, dass Sie nach Objekten und Arrays suchen , aber wenn Sie dies nicht tun UND Sie json_decodewas War zunächst ein einfaches Array, erhalten Sie beim Decodieren ein Array, kein Objekt. Sie müssen verwenden, JSON_FORCE_OBJECTwenn Sie ein Objekt immer für die Codierung erzwingen möchten, wenn ein einfaches Array übergeben wird.
Userabuser

11
Downvote für das Sagen : This request does not require a separate function even. Genau genommen erfordert keine Lösung eine separate Funktion. Der Sinn einer Funktion besteht nicht darin, mehrere Codezeilen wie eine Codezeile aussehen zu lassen. Der Zweck der Funktion besteht darin, den JSON-Überprüfungsprozess überall in Ihrer Anwendung zum Standard zu machen, damit verschiedene Programmierer (oder derselbe Programmierer im Laufe der Zeit) in verschiedenen Phasen des Programmablaufs keine unterschiedlichen Überprüfungsverfahren verwenden.
Cartbeforehorse

71

Mit json_decode"prüfen" ist dies möglicherweise nicht der schnellste Weg. Wenn es sich um eine tief verschachtelte Struktur handelt, ist es eine Verschwendung von Speicher und Zeit, viele Objekte von Arrays zu instanziieren, um sie einfach wegzuwerfen.

So ist es schneller sein könnte , zu verwenden preg_matchund der RFC4627 regex auch Gültigkeit zu gewährleisten :

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

Das gleiche in PHP:

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

Nicht genug von einem Performance-Enthusiasten, um sich hier mit Benchmarks zu beschäftigen.


11
Vervollständigen Sie den rekursiven regulären Ausdruck , um JSON hier zu überprüfen: stackoverflow.com/questions/2583472/regex-to-validate-json/… - Es stellt sich jedoch heraus, dass PHPs json_decodeimmer schneller sind als ein PCRE- regulärer Ausdruck . (Obwohl es nicht sehr optimiert ist, wurden keine synthetischen Tests gefunden und es könnte sich in Perl anders verhalten.)
Mario

3
@vee Ja, danke für den Hinweis. Aber lassen Sie es uns hier [falsch] behalten, damit niemand das tatsächlich in der Produktion verwendet.
Mario

1
@cartbeforehorse Okay, danke. Ich habe dann den für PHPs doppelten Zeichenfolgenkontext behoben.
Mario

1
@cartbeforehorse Das tut es nicht. Meistens Dekoration. Es ist nur der buchstäbliche Backslash, der tatsächlich ein doppeltes Entkommen erfordert. Denn \r \n \tes macht nur Sinn, damit PHP sie nicht interpoliert, sondern von PCRE interpretieren lässt (nur für den /xModus erforderlich ). Die anderen Vorkommnisse brauchen es nicht unbedingt; Dennoch "entgeht der Backslash sich selbst" in allen String-PHP-Kontexten. Man könnte es also genauer betrachten.
Mario

4
@ Mario Okay, ich verstehe. Im Grunde genommen entgeht das PHP den Backslashes, bevor die reg-exp-Engine es sieht. Was die reg-exp-Engine betrifft, gibt es die Hälfte der Backslashes in der Zeichenfolge, wie wir Menschen sehen. "Als
ob

39

Dies gibt true zurück, wenn Ihre Zeichenfolge ein JSON-Array oder -Objekt darstellt :

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

Es lehnt JSON-Zeichenfolgen ab, die nur eine Zahl, eine Zeichenfolge oder einen Booleschen Wert enthalten, obwohl diese Zeichenfolgen technisch gültige JSON-Zeichenfolgen sind.

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)

Es ist der kürzeste Weg, den ich finden kann.


Anstelle von var_dump können Sie dies in einen PHPUnit-Testfall einfügen. Ansonsten bin ich sowohl überrascht als auch froh zu erfahren, dass es wahr ist.
MrMesees

3
Warum haben alle anderen so langatmige Antworten, wenn dies großartig funktioniert? Vielen Dank.
Toddmo

1
Einfach wunderschön! Ich habe nicht nach dem "schnellsten Weg" oder der Leistung gesucht, aber dieser deckt sicher alle Fälle ab, nach denen ich jemals suchen würde. Dies ist ein klassisches Beispiel für das berüchtigte Sprichwort "Verwenden Sie keinen Vorschlaghammer, um eine Nuss zu knacken" . Aus Sicht eines Programmierers ist es immer besser, den Code einfach, kurz und leicht verständlich zu halten. Leistung und Einfachheit sind eine weitere Debatte, die für diesen Thread nicht in Frage kommt.
Fr0zenFyr

Dies ist ein ordentliches Stück Logik, aber beachten Sie auch, dass es für leere Arrays false zurückgibt. Zum Beispiel : var_dump(isJson('[]')); // bool(false). Laut der Dokumentation zu Booleschen Werten bewertet PHP Arrays mit Nullelementen als falsch. Hier ist eine geringfügige Änderung zur Anpassung der Rückgabeerklärung. es führt einen identischen Vergleich mit der decodierten Ausgabe durch, die diesen Fall behandelt:return $json !== false && $str != $json;
j13k

@ j13k Identischer Vergleich ergibt isJson('hello')true, was nicht gültig ist. Hier wird absichtlich ein loser Vergleich gewählt. Ich habe keine schnelle Lösung für die leere Array- / Objektsituation, außer einer hässlichenreturn $json == '[]' || ...
Cyril

21

Der einfachste und schnellste Weg, den ich benutze, ist der folgende;

$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

Dies liegt daran, dass json_decode () NULL zurückgibt, wenn die eingegebene Zeichenfolge nicht json oder ungültiger json ist.


Einfache Funktion zum Validieren von JSON

Wenn Sie Ihren JSON an mehreren Stellen validieren müssen, können Sie immer die folgende Funktion verwenden.

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

In der obigen Funktion erhalten Sie im Gegenzug true, wenn es sich um einen gültigen JSON handelt.


3
json_decode('null') == NULLund nullist ein gültiger JSON-Wert.
zzzzBov

Ich habe getestet, ob 'null' unter json.parser.online gültig ist, aber es scheint, dass es nicht gültig ist. Und json_decode () ist eine PHP-Kernfunktion zur Validierung von json, daher bezweifle ich, dass unsere Ausgabe ein falsches Ergebnis liefert .
Mohammad Mursaleen

Anstatt einer nicht verifizierten Website zu vertrauen, sollten Sie die Spezifikation konsultieren, die nicht übereinstimmt (S. 2) . Alternativ können Sie es auch JSON.parse('null')in Ihrer Entwicklungskonsole versuchen .
zzzzBov

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

http://tr.php.net/manual/en/function.json-decode.php Der Rückgabewert ist null, wenn eine ungültige Codierung festgestellt wird.


4
Es wird auch fälschlicherweise null für "null" zurückgegeben (was kein gültiger JSON ist, aber ansonsten möglicherweise vollständig "gültig" für json_decode ist). Stelle dir das vor.

Ich denke das sollte sein: json_decode($str)!=null;oder sonst sollte die Funktion aufgerufen werden is_not_json.
Yoshi

Diese Funktion sollte besser in "ist etwas anderes als JSON" umbenannt werden!
einsamer Tag

2
@ user166390, json_decode('null')ist gemäß der Spezifikation JSON gültig und sollte den Wert von zurückgeben null.
zzzzBov

Bitte beachten Sie auch, dass bei dieser Methode is_json('false')und is_json('[]')Rückgabe falseals Typ nicht aktiviert ist. Ich denke, diese Methode sollte eher zurückkehren $str === null || json_decode($str) !== null.
Antoine Pinsard

11

Sie müssen Ihre Eingabe überprüfen, um sicherzustellen, dass die übergebene Zeichenfolge nicht leer und tatsächlich eine Zeichenfolge ist. Eine leere Zeichenfolge ist kein gültiger JSON.

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

Ich denke , in PHP es wichtiger ist , zu bestimmen , ob das JSON - Objekt selbst hat Daten, da die Daten zu nutzen , müssen Sie anrufen json_encode()oder json_decode(). Ich schlage vor, leere JSON-Objekte zu verweigern, damit Sie nicht unnötig Codierungen und Decodierungen für leere Daten ausführen.

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 für das tatsächliche Nachdenken über das Problem in einem realen Kontext.
Cartbeforehorse

Aber '0'ist nicht gültig json ... warum sollte ich vorsichtig sein? @ Kzqai
upful

11

Dies wird es tun:

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()Gibt, wie in anderen Antworten gezeigt, alle Fehler von unserem letzten json_decode () zurück. Es gibt jedoch einige Edge-Anwendungsfälle, in denen diese Funktion allein nicht umfassend genug ist. Wenn Sie beispielsweise json_decode()eine Ganzzahl (z. B. :) 123oder eine Folge von Zahlen ohne Leerzeichen oder andere Zeichen (z. B. :) verwenden "123", wird die json_last_error()Funktion keinen Fehler abfangen.

Um dem entgegenzuwirken, habe ich einen zusätzlichen Schritt hinzugefügt, der sicherstellt, dass das Ergebnis json_decode()entweder ein Objekt oder ein Array ist. Wenn nicht, kehren wir zurück false.

Überprüfen Sie diese beiden Beispiele, um dies in Aktion zu sehen:


"hello"ist ein gültiger JSON, und es ist weder ein Objekt noch ein Array, json_last_error()ist genug
JoniJnm

1
json_last_error()Gibt einen Fehlercode zurück, 4wenn Sie json_decode()die Zeichenfolge eingeben "hello". Beispiel hier: 3v4l.org/lSsEo
Lewis Donovan

Ihr Code ist falsch, helloist kein gültiger JSON, aber "hello"ist 3v4l.org/OEJrQ
JoniJnm

9

Einfache Methode ist es, das JSON-Ergebnis zu überprüfen.

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

6

in 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

Früher habe ich nur nach einem Nullwert gesucht, was eigentlich falsch war.

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

Der obige Code funktioniert gut mit Zeichenfolgen. Sobald ich jedoch eine Nummer gebe, löst sie sich auf. Zum Beispiel.

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

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

Es war sehr einfach, das zu reparieren, was ich getan habe.

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

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

Schöne Lösung. Behandelt das Tippproblem sehr gut!
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

Ein anderer einfacher Weg

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

1
Das ist nicht richtig. Jeder PHP-Typ kann in JSON codiert werden, z. B. Objekte, Zeichenfolgen usw., und es wird erwartet, dass die Funktion json_decode diese zurückgibt. Dies gilt nur, wenn Sie immer Arrays und keine anderen Variablentypen dekodieren.
Chaoix

Mit @Chaoix werden json_decode($str,true)Objekte in Arrays konvertiert, sodass die Prüfung is_array bestanden wird. Sie korrigieren jedoch Zeichenfolgen, Ganzzahlen usw.
Paul Phillips

Ich sehe, was Sie mit dem zweiten Parameter auf json_encode meinen. Ich denke immer noch, dass die Lösung von @Ahad Ali viel besser ist, wenn es darum geht, zu tippen und einen json_decode nur einmal in Ihren Algorithmen auszuführen.
Chaoix

4

Wir müssen überprüfen, ob die übergebene Zeichenfolge nicht numerisch ist, da in diesem Fall json_decode keinen Fehler auslöst.

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

    return $result;
}

4

Ich habe diese Frage gefunden, nachdem ich gestern in meiner Arbeit auf etwas Ähnliches gestoßen bin. Meine Lösung war am Ende eine Mischung aus einigen der oben genannten Ansätze:

function is_JSON($string) {

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

  return $String_Is_JSON;
}

3

Ich habe einige dieser Lösungen ausprobiert, aber nichts hat für mich funktioniert. Ich versuche diese einfache Sache:

$isJson = json_decode($myJSON);

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

Ich denke, es ist eine gute Lösung, da JSON-Dekodierung ohne den zweiten Parameter ein Objekt ergibt.

BEARBEITEN: Wenn Sie wissen, was die Eingabe sein wird, können Sie diesen Code an Ihre Bedürfnisse anpassen. In meinem Fall weiß ich, dass ich einen Json habe, der mit "{" beginnt, daher muss ich nicht überprüfen, ob es sich um ein Array handelt.


Ihr JSON könnte möglicherweise nur ein Array sein. In diesem Fall wäre es eher ein Array als anstelle von 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

Unter Verwendung von PHPBench mit der folgenden Klasse wurden die folgenden Ergebnisse erzielt:

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

Fazit: Der schnellste Weg, um zu überprüfen, ob json gültig ist, ist die Rückkehr json_decode($json, true) !== null).


sehr schön :) ich bewundere dich
Mahdi

2

Ich weiß nichts über die Leistung oder Eleganz meiner Lösung, aber ich verwende Folgendes:

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

Da alle meine JSON-codierten Zeichenfolgen mit {"beginnen, reicht es aus, dies mit einem RegEx zu testen. Ich spreche überhaupt nicht fließend mit RegEx, daher gibt es möglicherweise einen besseren Weg, dies zu tun. Außerdem: strpos () ist möglicherweise schneller.

Ich versuche nur, meine Tuppence wert zu geben.

PS Gerade die RegEx-Zeichenfolge aktualisiert, /^[\[\{]\"/um auch JSON-Array-Zeichenfolgen zu finden. Daher wird am Anfang des Strings entweder nach ["oder {" gesucht.


2

Sollte so etwas sein:

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

Gerätetest

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

Ich finde es gut, dass Sie prüfen, ob es sich um eine Zeichenfolge handelt. Passt gut in Kombination mit der ersten Lösung, um zu vermeiden, ErrorExceptionob die Zeichenfolge ein Array oder ein Objekt ist.
Sykez

1

Erweitern dieser Antwort Wie wäre es mit Folgendem:

<?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
Sollte die Teilzeichenfolgenprüfung nicht vor dem Ausführen der Dekodierung durchgeführt werden, um Zeit zu sparen, wenn der Fehler in dieser Prüfung gefunden wird? Ich würde mir vorstellen, dass 4 Teilstring-Prüfungen schneller sind als ein json_decode, aber wenn mich jemand mit dieser Annahme unterstützen könnte, würde ich mich über Gedanken dazu freuen.
Mark

Das ist ein Tarifargument. Ich kenne die Bearbeitungszeit nicht, aber wenn es schneller ist, dann ja.
Sevenearths

1

Hallo, hier ist ein kleiner Ausschnitt aus meiner Bibliothek. In diesem ersten Zustand überprüfe ich nur, ob die Daten json sind, und gebe sie dann zurück, wenn sie korrekt dekodiert sind. Bitte beachten Sie die Substr-Verwendung für die Leistung (ich habe noch keine json-Datei gesehen, die auch nicht beginnt von {oder [

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

Es wurden 34 Antworten auf diese Frage veröffentlicht, von denen viele auch die (falsche) Überzeugung vertreten, dass JSON ein Array oder ein Objekt darstellen muss. Unterscheidet sich diese Antwort von den anderen 3 Dutzend Antworten?
miken32

1

Ein weiterer Vorschlag von mir :)

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

0

Die benutzerdefinierte Funktion

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

Fälle

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

}

Ressourcen

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


0

Frisch erstellte Funktion für PHP 5.2-Kompatibilität, wenn Sie die dekodierten Daten für den Erfolg benötigen:

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

Verwendungszweck:

$json_or_not = ...;

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

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

Einige Tests:

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
@ Verwenden Sie für das Debuggen (versteckt einen Fehler), aber es ist absolut nicht zu empfehlen
aswzen

0

Eine einfache Modifikation von Henriks Antwort, um die meisten erforderlichen Möglichkeiten zu berühren.

(einschließlich "{} und []")

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

Der schnellste Weg , um vielleicht zu entschlüsseln ein mögliche JSON - Objekt an einem PHP - Objekt / Array:

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

Hier ist eine performante und einfache Funktion, die ich erstellt habe (die die grundlegende Zeichenfolgenüberprüfung verwendet, bevor sie json_decodefür größere Zeichenfolgen verwendet wird):

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;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.