web-dev-qa-db-fra.com

Comment résoudre l'erreur JSON_ERROR_UTF8 dans php json_decode?

J'essaye ce code

$json = file_get_contents("http://www.google.com/alerts/preview?q=test&t=7&f=1&l=0&e");
print_r(json_decode(utf8_encode($json), true));

        //////////////

// Define the errors.
$constants = get_defined_constants(true);
$json_errors = array();
foreach ($constants["json"] as $name => $value) {
    if (!strncmp($name, "JSON_ERROR_", 11)) {
        $json_errors[$value] = $name;
    }
}

// Show the errors for different depths.
foreach (range(4, 3, -1) as $depth) {
    var_dump(json_decode($json, true, $depth));
    echo 'Last error: ', $json_errors[json_last_error()], PHP_EOL, PHP_EOL;
}

J'ai essayé beaucoup de fonctions, html_entities_decode, utf8_encode et decode, décodant les codes hexadécimaux, mais j'obtiens toujours l'erreur "JSON_ERROR_UTF8".

Comment pourrais-je résoudre ce problème?

47
James Harzs

Il y a une bonne fonction pour assainir vos tableaux.

Je vous suggère d'utiliser un wrapper json_encode comme celui-ci:

function safe_json_encode($value, $options = 0, $depth = 512, $utfErrorFlag = false) {
    $encoded = json_encode($value, $options, $depth);
    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            return $encoded;
        case JSON_ERROR_DEPTH:
            return 'Maximum stack depth exceeded'; // or trigger_error() or throw new Exception()
        case JSON_ERROR_STATE_MISMATCH:
            return 'Underflow or the modes mismatch'; // or trigger_error() or throw new Exception()
        case JSON_ERROR_CTRL_CHAR:
            return 'Unexpected control character found';
        case JSON_ERROR_SYNTAX:
            return 'Syntax error, malformed JSON'; // or trigger_error() or throw new Exception()
        case JSON_ERROR_UTF8:
            $clean = utf8ize($value);
            if ($utfErrorFlag) {
                return 'UTF8 encoding error'; // or trigger_error() or throw new Exception()
            }
            return safe_json_encode($clean, $options, $depth, true);
        default:
            return 'Unknown error'; // or trigger_error() or throw new Exception()

    }
}

function utf8ize($mixed) {
    if (is_array($mixed)) {
        foreach ($mixed as $key => $value) {
            $mixed[$key] = utf8ize($value);
        }
    } else if (is_string ($mixed)) {
        return utf8_encode($mixed);
    }
    return $mixed;
}

Dans mon application, utf8_encode () fonctionne mieux que iconv ()

72
Konstantin

Vous avez besoin d'une simple ligne de code:

$input = iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($input));
$json = json_decode($input);

Crédit: Sang Le, mon coéquipier m'a donné ce code. Ouais!

54
Andy Truong

La fonction iconv est sans valeur, sauf si vous pouvez garantir que l'entrée est valide. Utilisez plutôt mb_convert_encoding.

mb_convert_encoding($value, "UTF-8", "auto");

Vous pouvez être plus explicite que "auto" et même spécifier une liste séparée par des virgules des encodages d'entrée attendus.

Plus important encore, les caractères invalides seront traités sans entraîner la suppression de la chaîne entière (contrairement à iconv).

11
Rich Remer

Décodage JSON en PHP Le décodage JSON est aussi simple que de l'encoder. PHP vous fournit une fonction json_decode pratique qui gère tout pour vous. Si vous passez simplement une chaîne JSON valide dans la méthode, vous obtenez un objet de type stdClass. Voici un petit exemple:

<?php
$string = '{"foo": "bar", "cool": "attr"}';
$result = json_decode($string);

// Result: object(stdClass)#1 (2) { ["foo"]=> string(3) "bar" ["cool"]=> string(4) "attr" }
var_dump($result);

// Prints "bar"
echo $result->foo;

// Prints "attr"
echo $result->cool;
?>

Si vous souhaitez récupérer un tableau associatif à la place, définissez le deuxième paramètre sur true:

<?php
$string = '{"foo": "bar", "cool": "attr"}';
$result = json_decode($string, true);

// Result: array(2) { ["foo"]=> string(3) "bar" ["cool"]=> string(4) "attr" }
var_dump($result);

// Prints "bar"
echo $result['foo'];

// Prints "attr"
echo $result['cool'];
?>

Si vous attendez un document JSON imbriqué très volumineux, vous pouvez limiter la profondeur de récursivité à un certain niveau. La fonction retourne null et arrête l'analyse si le document est plus profond que la profondeur donnée.

<?php
$string = '{"foo": {"bar": {"cool": "value"}}}';
$result = json_decode($string, true, 2);

// Result: null
var_dump($result);
?>

Le dernier argument fonctionne de la même manière que dans json_encode, mais il n'y a qu'un seul masque de bits pris en charge actuellement (qui vous permet de convertir des bigints en chaînes et n'est disponible qu'à partir de PHP 5.4 vers le haut)). travailler avec des chaînes JSON valides jusqu'à présent (à part l'erreur de profondeur nulle). La partie suivante vous montre comment gérer les erreurs.

Traitement des erreurs et test Si la valeur JSON n'a pas pu être analysée ou si un niveau d'imbrication plus profond que la profondeur donnée (ou par défaut) est trouvé, NULL est renvoyé de json_decode. Cela signifie qu'aucune exception n'est levée directement par json_encode/json_deocde.

Alors, comment pouvons-nous identifier la cause de l'erreur? La fonction json_last_error aide ici. json_last_error renvoie un code d'erreur entier qui peut être l'une des constantes suivantes (extraites d'ici):

JSON_ERROR_NONE: Aucune erreur ne s'est produite. JSON_ERROR_DEPTH: la profondeur de pile maximale a été dépassée. JSON_ERROR_STATE_MISMATCH: JSON invalide ou mal formé. JSON_ERROR_CTRL_CHAR: erreur de caractère de contrôle, peut-être encodée de manière incorrecte. JSON_ERROR_SYNTAX: Erreur de syntaxe. JSON_ERROR_UTF8: caractères UTF-8 mal formés, éventuellement mal encodés (depuis PHP 5.3.3). Avec ces informations à portée de main, nous pouvons écrire une méthode d'aide à l'analyse rapide qui déclenche une exception descriptive en cas d'erreur est trouvé.

<?php
class JsonHandler {

    protected static $_messages = array(
        JSON_ERROR_NONE => 'No error has occurred',
        JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded',
        JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON',
        JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
        JSON_ERROR_SYNTAX => 'Syntax error',
        JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded'
    );

    public static function encode($value, $options = 0) {
        $result = json_encode($value, $options);

        if($result)  {
            return $result;
        }

        throw new RuntimeException(static::$_messages[json_last_error()]);
    }

    public static function decode($json, $assoc = false) {
        $result = json_decode($json, $assoc);

        if($result) {
            return $result;
        }

        throw new RuntimeException(static::$_messages[json_last_error()]);
    }

}
?>

Nous pouvons maintenant utiliser la fonction de test d'exception du dernier message sur la gestion des exceptions pour tester si notre exception fonctionne correctement.

// Returns "Correctly thrown"
assertException("Syntax error", function() {
    $string = '{"foo": {"bar": {"cool": NONUMBER}}}';
    $result = JsonHandler::decode($string);
});

Notez que depuis PHP 5.3.3, une erreur JSON_ERROR_UTF8 est renvoyée lorsqu'un caractère UTF-8 non valide est trouvé dans la chaîne. Ceci est une forte indication qu'un jeu de caractères différent de UTF-8 est Si la chaîne entrante n'est pas sous votre contrôle, vous pouvez utiliser la fonction utf8_encode pour la convertir en utf8.

<?php echo utf8_encode(json_encode($payload)); ?>

Je l'ai utilisé par le passé pour convertir des données chargées à partir d'une base de données MSSQL héritée qui n'utilisait pas UTF-8.

source

0
Muhammad Tahir