web-dev-qa-db-fra.com

PHP json_decode () renvoie NULL avec un code JSON valide?

J'ai cet objet JSON stocké dans un fichier texte:

{
    "MySQL": {
        "Server": "(server)",
        "Username": "(user)",
        "Password": "(pwd)",
        "DatabaseName": "(dbname)"
    },
    "Ftp": {
        "Server": "(server)",
        "Username": "(user)",
        "Password": "(pwd)",
        "RootFolder": "(rf)"
    },
    "BasePath": "../../bin/",
    "NotesAppPath": "notas",
    "SearchAppPath": "buscar",
    "BaseUrl": "http:\/\/montemaiztusitio.com.ar",
    "InitialExtensions": [
        "nem.mysqlhandler",
        "nem.string",
        "nem.colour",
        "nem.filesystem",
        "nem.rss",
        "nem.date",
        "nem.template",
        "nem.media",
        "nem.measuring",
        "nem.weather",
        "nem.currency"
    ],
    "MediaPath": "media",
    "MediaGalleriesTable": "journal_media_galleries",
    "MediaTable": "journal_media",
    "Journal": {
        "AllowedAdFileFormats": [
            "flv:1",
            "jpg:2",
            "gif:3",
            "png:4",
            "swf:5"
        ],
        "AdColumnId": "3",
        "RSSLinkFormat": "%DOMAIN%\/notas\/%YEAR%-%MONTH%-%DAY%\/%TITLE%/",
        "FrontendLayout": "Flat",
        "AdPath": "ad",
        "SiteTitle": "Monte Maíz: Tu Sitio",
        "GlobalSiteDescription": "Periódico local de Monte Maíz.",
        "MoreInfoAt": "Más información aquí, en el Periódico local de Monte Maíz.",
        "TemplatePath": "templates",
        "WeatherSource": "accuweather:SAM|AR|AR005|MONTE MAIZ",
        "WeatherMeasureType": "1",
        "CurrencySource": "cotizacion-monedas:Dolar|Euro|Real",
        "TimesSingular": "vez",
        "TimesPlural": "veces"
    }
}

Lorsque j'essaie de le décoder avec json_decode(), il renvoie NULL. Pourquoi? Le fichier est lisible (j'ai essayé de faire écho à file_get_contents() et tout a bien fonctionné).

J'ai testé JSON contre http://jsonlint.com/ et il est parfaitement valide.

Quel est le problème ici?

Solution

À la recherche de réponses sur Google, je suis retourné à SO: json_decode renvoie NULL après l'appel du service Web . Mon fichier JSON avait la séquence de nomenclature UTF (quelques caractères binaires qui ne devraient pas être là), cassant ainsi la structure JSON. Je suis allé à Hex Editor, j'ai effacé les octets. Tout est revenu à la normale… Pourquoi est-ce arrivé? Parce que j'ai édité le fichier en utilisant le Bloc-notes de Microsoft Windows. Terrible idée!

Ce pourrait être l'encodage des caractères spéciaux. Vous pouvez demander à json_last_error () d’obtenir des informations précises.

Mise à jour: Le problème est résolu, consultez le paragraphe "Solution" de la question.

55
Pekka 웃

Cela a fonctionné pour moi 

json_decode( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $json_string), true );
56
Dunith Dhanushka

Si vous cochez la demande dans chrome, vous verrez que le JSON est du texte. Un code vierge a donc été ajouté au JSON.

Vous pouvez effacer en utilisant

$k=preg_replace('/\s+/', '',$k);

Ensuite, vous pouvez utiliser:

json_decode($k)

print_r montrera alors le tableau.

23
user2254008

Tu pourrais essayer avec. 

json_decode(stripslashes($_POST['data']))
15

J'ai eu le même problème et je l'ai résolu simplement en remplaçant le caractère de citation avant décodage.

$json = str_replace('"', '"', $json);
$object = json_decode($json);

Ma valeur JSON a été générée par la fonction JSON.stringify.

12
Yapp Ka Howe

Peut-être que certains personnages cachés jouent avec votre json, essayez ceci:

$json = utf8_encode($yourString);
$data = json_decode($json);
9
Albert Abdonor
$k=preg_replace('/\s+/', '',$k); 

l'a fait pour moi. Et oui, tester sur Chrome. Thx à user2254008

6
Jürgen Math

Je pensais juste ajouter ceci, car je suis tombé sur cette question aujourd'hui. Si une chaîne de remplissage entoure votre chaîne JSON, json_decode retournera NULL.

Si vous extrayez le JSON d'une source autre qu'une variable PHP, il serait judicieux de le "rogner" en premier:

$jsonData = trim($jsonData);
4
Phil LaNasa

cela vous aide à comprendre quel est le type d'erreur

<?php
// A valid json string
$json[] = '{"Organization": "PHP Documentation Team"}';

// An invalid json string which will cause an syntax 
// error, in this case we used ' instead of " for quotation
$json[] = "{'Organization': 'PHP Documentation Team'}";


foreach ($json as $string) {
    echo 'Decoding: ' . $string;
    json_decode($string);

    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            echo ' - No errors';
        break;
        case JSON_ERROR_DEPTH:
            echo ' - Maximum stack depth exceeded';
        break;
        case JSON_ERROR_STATE_MISMATCH:
            echo ' - Underflow or the modes mismatch';
        break;
        case JSON_ERROR_CTRL_CHAR:
            echo ' - Unexpected control character found';
        break;
        case JSON_ERROR_SYNTAX:
            echo ' - Syntax error, malformed JSON';
        break;
        case JSON_ERROR_UTF8:
            echo ' - Malformed UTF-8 characters, possibly incorrectly encoded';
        break;
        default:
            echo ' - Unknown error';
        break;
    }

    echo PHP_EOL;
}
?>
2
Enrico Tempesti

Si vous obtenez JSON de la base de données, mettez

mysqli_set_charset($con, "utf8");

après avoir défini le lien de connexion $ con

1
TomoMiha

Économisez juste une fois. J'ai passé 3 heures à découvrir qu'il s'agissait simplement d'un problème d'encodage HTML. Essaye ça 

if(get_magic_quotes_gpc()){
   $param = stripslashes($row['your column name']);
}else{
  $param = $row['your column name'];
}

$param = json_decode(html_entity_decode($param),true);
$json_errors = array(
JSON_ERROR_NONE => 'No error has occurred',
JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded',
JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
JSON_ERROR_SYNTAX => 'Syntax error',
);
echo 'Last error : ', $json_errors[json_last_error()], PHP_EOL, PHP_EOL;
print_r($param);
1
Samuel Kwame Antwi

Vous trouverez ici un petit wrapper JSON avec des actions correctives qui répondent aux problèmes de nomenclature et non ASCI: https://stackoverflow.com/a/43694325/2254935

1
Krzysztof Przygoda

Comme l'a déclaré Jürgen Math en utilisant la méthode preg_replace listée par user2254008, elle l'a également corrigée.

Cela ne se limite pas à Chrome, il semble s'agir d'un problème de conversion de jeux de caractères (du moins dans mon cas, Unicode -> UTF8). Cela corrigeait tous les problèmes que j'avais.

En tant que futur nœud, l’objet JSON que j’étais en train de décoder provenait de la fonction json.dumps de Python. Cela a ensuite amené certaines données insalubres à être transmises, même si elles ont été traitées facilement.

1
Destreyf

vous devez vous assurer de ces points

1. votre chaîne json n'a pas de caractères inconnus

2. La chaîne/json peut être visualisée à partir du visualiseur json en ligne (vous pouvez effectuer une recherche sur Google en tant que visualiseur en ligne ou analyseur syntaxique pour json).

3. votre chaîne ne possède pas d'entités HTML, elle doit être en texte brut/chaîne

pour l'explication du point 3 

$html_product_sizes_json=htmlentities($html);
    $ProductSizesArr = json_decode($html_product_sizes_json,true);

to (supprime la fonction htmlentities ())

$html_product_sizes_json=$html;
    $ProductSizesArr = json_decode($html_product_sizes_json,true);
0
Hassan Saeed

Dans mon cas, c'est à cause des guillemets simples dans la chaîne JSON.

Le format JSON accepte uniquement les guillemets doubles pour les clés et les valeurs de chaîne.

Exemple:

$jsonString = '{\'hello\': \'PHP\'}'; // valid value should be '{"hello": "PHP"}'
$json = json_decode($jsonString);
print $json; // null

J'ai eu cela déroutant à cause de la syntaxe Javascript. En Javascript, bien sûr, on peut faire comme ça:

let json = {
    hello: 'PHP' // no quote for key, single quote for string value
}

// OR:
json = {
    'hello': 'PHP' // single quote for key and value
}

mais plus tard, lors de la conversion de ces objets en chaîne JSON:

JSON.stringify(json); // "{"hello":"PHP"}"
0
Tho

J'ai résolu ce problème en imprimant le JSON, puis en vérifiant le code source de la page (CTRL/CMD + U):

print_r(file_get_contents($url));

Il s'est avéré qu'il y avait une dernière balise <pre>.

0
Jeffrey Roosendaal