550 Stimmen

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

Ich brauche eine wirklich, wirklich schnelle Methode der Überprüfung, ob eine Zeichenfolge JSON ist oder nicht. Ich fühle mich wie dies ist nicht der beste Weg:

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

Gibt es da draußen Leistungsenthusiasten, die diese Methode verbessern wollen?

34voto

Philipp Punkte 8320

Der schnellste Weg ist " vielleicht entschlüsseln " die mögliche JSON-Zeichenkette

Ist dies wirklich die schnellste Methode?

Wenn Sie komplexe Objekte oder größere Arrays dekodieren wollen, ist dies die schnellste Lösung ! Abgesehen davon, dass es schnell ist, ist dies die einzige Lösung, die zuverlässig jede Art von Eingabewert verarbeiten - andere Funktionen werfen Fehler oder liefern in manchen Fällen falsche Ergebnisse.

Wenn Ihre JSON-Zeichenfolge kurze Werte enthält (z. B. Zeichenketten, Zahlen oder Objekte mit nur 1-2 Attributen), dann kommen alle Lösungen in dieser SO-Fragen zu einem ähnliche Leistung .

Hier ist ein kurzer Überblick mit Vergleich - die Testfälle finden Sie im verlinkten Gist. Die letzte Spalte verwendet den Code aus dieser Antwort:

PHP version: 7.4.21

test1: json_last_error() == JSON_ERROR_NONE
test2: is_object( json_decode() )
test3: json_decode() && $res != $string
test4: preg_match()
test5: "maybe decode" approach

      | test1    | test2    | test3    | test4    | test5    
   #0 | 0.0147   | 0.0109  | 0.0119   | 0.0177   | 0.0194   
   #1 | 0.0129   | 0.0106   | 0.0098   | - INV -  | 0.0078  
   #2 | 0.0076   | 0.0075   | 0.0063  | 0.0083   | 0.0133   
   #3 | 0.0126   | 0.0105   | 0.0096  | - INV -  | 0.0172   
   #4 | 0.0070   | - INV -  | 0.0061  | 0.0141   | 0.0134   
   #5 | 0.0114   | - INV -  | 0.0101   | 0.0075  | 0.0168   
   #6 | 0.0203   | - INV -  | 0.0195   | 0.0073  | 0.0259   
   #7 | 0.0046   | - INV -  | - INV -  | 0.0077   | 0.0031  
   #8 | 0.0066   | - INV -  | - INV -  | 0.0081   | 0.0020  
   #9 | 1.0781   | - INV -  | 1.0555   | 0.0998  | 1.0385   
  #10 | 0.3183  | 0.3246   | 0.3270   | 1.0186   | 0.3311   
  #11 | 0.0071   | 0.0068   | 0.0067  | - INV -  | 0.0079   
  #12 | - ERR -  | - ERR -  | - ERR -  | - ERR -  | 0.0025  
  #13 | - ERR -  | - ERR -  | - ERR -  | - ERR -  | 0.0024  
  Avg | 0.1251   | 0.0618  | 0.1463   | 0.1321   | 0.1072

Beachten Sie, dass die schnellste Lösung die meisten falschen Ergebnisse liefert. Von allen anderen Lösungen ist der Ansatz "maybe decode" nicht nur die schnellste, sondern auch die einzige Lösung mit korrekten Ergebnissen.

Hier ist das vollständige Skript für den Leistungsvergleich, dort können Sie die Testdaten sehen, die ich für den Vergleich verwendet habe: https://gist.github.com/stracker-phil/6a80e6faedea8dab090b4bf6668ee461


Die Logik/der Code "vielleicht entschlüsseln

Wir führen zunächst einige Typüberprüfungen und Stringvergleiche durch, bevor wir versuchen, den JSON-String zu dekodieren. Dies bringt uns die beste Leistung, da json_decode() langsam sein kann.

/**
 * Returns true, when the given parameter is a valid JSON string.
 */
function is_json( $value ) {
    // Numeric strings are always valid JSON.
    if ( is_numeric( $value ) ) { return true; }

    // A non-string value can never be a JSON string.
    if ( ! is_string( $value ) ) { return false; }

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

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

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

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

    // Verify that the trailing character matches the first character.
    $last_char = $value[strlen($value) -1];
    if ( '{' == $value[0] && '}' != $last_char ) { return false; }
    if ( '[' == $value[0] && ']' != $last_char ) { return false; }
    if ( '"' == $value[0] && '"' != $last_char ) { return false; }

    // See if the string contents are valid JSON.
    return null !== json_decode( $value );
}

Extra: Verwenden Sie diese Logik, um JSON sicher doppelt zu dekodieren

Diese Funktion verwendet die gleiche Logik, aber entweder gibt das dekodierte JSON-Objekt zurück oder die ursprünglicher Wert .

Ich verwende diese Funktion in einem Parser, der ein komplexes Objekt rekursiv dekodiert. Einige Attribute könnten bereits in einer früheren Iteration dekodiert worden sein. Diese Funktion erkennt dies und versucht nicht, den Wert noch einmal zu dekodieren.

/**
 * Tests, if the given $value parameter is a JSON string.
 * When it is a valid JSON value, the decoded value is returned.
 * When the value is no JSON value (i.e. it was decoded already), then 
 * the original value is returned.
 */
function get_data( $value, $as_object = false ) {
    if ( is_numeric( $value ) ) { return 0 + $value; }
    if ( ! is_string( $value ) ) { return $value; }
    if ( strlen( $value ) < 2 ) { return $value; }
    if ( 'null' === $value ) { return null; }
    if ( 'true' === $value ) { return true; }
    if ( 'false' === $value ) { return false; }
    if ( '{' != $value[0] && '[' != $value[0] && '"' != $value[0] ) { return $value; }

    $json_data = json_decode( $value, $as_object );
    if ( is_null( $json_data ) ) { return $value; }
    return $json_data;
}

Hinweis: Bei der Übergabe einer Nicht-String zu einer der anderen Lösungen in dieser SO-Frage, erhalten Sie dramatisch verschlechterte Leistung + falsche Rückgabewerte (oder sogar fatale Fehler). Dieser Code ist kugelsicher und hoch performant.

29voto

upful Punkte 770

Sie müssen Ihre Eingabe validieren, um sicherzustellen, dass die übergebene Zeichenkette nicht leer ist und tatsächlich eine Zeichenkette darstellt. Eine leere Zeichenfolge ist kein gültiges 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 ist es wichtiger zu bestimmen, ob das JSON-Objekt sogar hat Daten, denn um die Daten zu verwenden, müssen Sie die json_encode() o json_decode() . Ich schlage vor, leere JSON-Objekte zu verweigern, damit Sie nicht unnötig Kodierungen und Dekodierungen auf leeren Daten durchfü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;
}

29voto

Die einfachste und schnellste Methode, die ich verwende, ist 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

Das ist so, weil json_decode() gibt NULL zurück, wenn die eingegebene Zeichenkette nicht json oder ungültig json ist.

Einfache Funktion zur Validierung von JSON

Wenn Sie Ihr 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 true zurück, wenn es ein gültiges JSON ist.

25voto

ahmet alp balkan Punkte 38500
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 Kodierung erkannt wird.

16voto

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

function is_JSON($string) {

    return is_null(json_decode($string));
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X