PHP json_decode () devuelve NULL con JSON válido?

104

Tengo este objeto JSON almacenado en un archivo de texto sin formato:

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

Cuando intento decodificarlo json_decode(), devuelve NULL. ¿Por qué? El archivo es legible (intenté hacer eco file_get_contents()y funcionó bien).

Probé JSON contra http://jsonlint.com/ y es perfectamente válido.

¿Qué pasa aquí?

Solución

Buscando respuestas en Google, volví a SO: json_decode devuelve NULL después de la llamada al servicio web . Mi archivo JSON tenía la secuencia UTF BOM (algunos caracteres binarios que no deberían estar allí), rompiendo así la estructura JSON. Fui al editor hexadecimal, borré los bytes. Todo volvió a la normalidad. ¿Por qué ha sucedido esto? Porque edité el archivo usando el Bloc de notas de Microsoft Windows. ¡Terrible idea!

Joel A. Villarreal Bertoldi
fuente
5
Trabajando con PHP 5.2.9; por lo tanto, no puedo usar json_last_error().
Joel A. Villarreal Bertoldi
1
También tenga en cuenta que esto puede suceder con otros caracteres no válidos en el medio del archivo. Acabo de tener json_decode () devolviendo nulo porque la cadena contenía uno de esos guiones especiales, probablemente pegado de MS Word, y luego tal vez mal codificado. Para identificar posibles caracteres problemáticos, abra el archivo JSON (que usé en Notepad ++), cambie la codificación (sin convertir) y guárdelo como una copia. Luego diferencie los dos archivos (usé WinMerge).
LinusR
(Problema del Bloc de notas de Windows) Por favor, consulte esto, también compartí el problema y lo solucionó: stackoverflow.com/questions/10290849/…
Felix Aballi
Para mí, no fue nada especial, solo una coma adicional al final del elemento de un objeto. Quitar: cualquier cosa que haga que su JSON sea inconsistente generará un error. Consejo adicional: no confíe en jsonviewer.stack.hu Use algo como jsonlint
Aman Alam

Respuestas:

68

Podría ser la codificación de los caracteres especiales. Puede pedirle a json_last_error () que obtenga información definitiva.

Actualización: el problema está resuelto, consulte el párrafo "Solución" de la pregunta.

Pekka
fuente
He estado usando los caracteres especiales desde que inicié la aplicación y antes no había problemas. A nivel local, la decodificación JSON funciona perfectamente. En mi servidor, no es así. Y no puedo llamar json_last_error()porque es PHP 5.2.9. Esa función aparece en PHP 5.3.0.
Joel A. Villarreal Bertoldi
1
No, esto debería funcionar. No puedo hacer más pruebas en este momento, si lo hago más tarde, publicaré aquí. También hay algunas sugerencias en las notas aportadas por el usuario: de.php.net/json_decode tal vez algo ayude.
Pekka
1
Para mí, en PHP 5.3, funciona bien cuando el texto está codificado en UTF-8. Pero si paso el texto utf8_decode()primero, entonces json_decode()falla silenciosamente.
Mateo
1
@Pekka Buscando respuestas en Google, volví a SO: stackoverflow.com/questions/689185/json-decode-returns-null-php . Mi archivo JSON tenía la secuencia UTF BOM (algunos caracteres binarios que no deberían estar allí), rompiendo así la estructura JSON. Fui al editor hexadecimal, borré los bytes. Todo volvió a la normalidad. ¿Por qué ha sucedido esto? Porque edité el archivo usando el Bloc de notas de Micro $ oft Windows. ¡Terrible idea!
Joel A. Villarreal Bertoldi
2
Esto debería notificarse como un error a la gente de PHP. Si la lista de materiales era UTF8 válida, no debería ahogarse silenciosamente.
jmucchiello
86

Esto funcionó para mi

json_decode( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $json_string), true );
Dunith Dhanushka
fuente
2
He usado esto y obtuve la matriz, pero los caracteres específicos de mi idioma (ş, ç, ö, ..) también se han eliminado.
zkanoca
5
Esto no es correcto si los datos json están codificados en UTF-8 (o cualquier codificación UTF, supongo). Eliminará los datos codificados en UTF-8 válidos. Probablemente funcione siempre que el archivo solo contenga el idioma inglés, pero eso siempre es una suposición arriesgada. Yo no usaría esto.
DaedalusAlpha
Con esto funciona pero sin él no, aunque las dos cadenas sean idénticas, ¿me falta algo?
Rudie Visser
funciona! ¿pero por qué? la cadena que intenté decodificar no tenía ningún carácter especial
Tobias Gassmann
Increíble. Trabajó para mi. :)
Sohil
31

Podrías intentarlo.

json_decode(stripslashes($_POST['data']))
Gabriel Castillo Prada
fuente
Accidentalmente llamé stripslashes()dos veces, lo que eliminó las barras inclinadas esenciales y causó una cadena JSON no válida. Esta respuesta me ayudó a detectar el error
Philipp hace
22

Si marca la solicitud en Chrome, verá que el JSON es texto, por lo que se ha agregado un código en blanco al JSON.

Puedes borrarlo usando

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

Entonces puedes usar:

json_decode($k)

print_r luego mostrará la matriz.

usuario2254008
fuente
Gracias por esto, espero que encuentres el inglés que te falta.
Dean_Wilson
Hombre, eres una leyenda, has estado lidiando con esto todo el día.
Sboniso Marcus Nzimande
¡Lo hice por mí! Un simple ajuste que hice fue agregar un espacio en el reemplazo, estoy usando esto y parece que también reemplaza mi espacio. funciona bien ahora. $k=preg_replace('/\s+/', ' ',$k);
Kash
El problema es que esto elimina todos los espacios, haciendo que el texto en inglés se pegue, ¿no es así?
CodeGuru
14

Tuve el mismo problema y lo resolví simplemente reemplazando el carácter de cita antes de decodificar.

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

Mi valor JSON fue generado por la función JSON.stringify.

Yapp Ka Howe
fuente
En este caso, es posible que se esté utilizando la función htmlspecialchars y el JSON ya no se puede analizar. Para revertirlo existe la función "htmlspecialchars_decode" en lugar de reemplazar manualmente & quot;
Davy
11

Tal vez algunos personajes ocultos estén jugando con su json, intente esto:

$json = utf8_encode($yourString);
$data = json_decode($json);
Albert Abdonor
fuente
Después de probar todas las soluciones anteriores, esta finalmente funcionó para mí. ¡¡Gracias una tonelada!!
Anis R.
7
$k=preg_replace('/\s+/', '',$k); 

lo hizo por mí. Y sí, probando en Chrome. Gracias al usuario2254008

Jürgen Math
fuente
4

Solo pensé en agregar esto, ya que me encontré con este problema hoy. Si hay algún relleno de cadena alrededor de su cadena JSON, json_decode devolverá NULL.

Si está extrayendo el JSON de una fuente que no sea una variable de PHP, sería prudente "recortarlo" primero:

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

esto le ayudará a comprender cuál es el tipo de error

<?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;
}
?>
Enrico Tempesti
fuente
2

Solo guarda algo una vez. Pasé 3 horas para descubrir que era solo un problema de codificación html. Prueba esto

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);
Samuel Kwame Antwi
fuente
1

Como lo indicó Jürgen Math, el uso del método preg_replace enumerado por user2254008 también lo solucionó para mí.

Esto no se limita a Chrome, parece ser un problema de conversión de juego de caracteres (al menos en mi caso, Unicode -> UTF8) Esto solucionó todos los problemas que estaba teniendo.

Como nodo futuro, el objeto JSON que estaba decodificando provino de la función json.dumps de Python. Esto, a su vez, provocó que otros datos insalubres aparecieran, aunque se trató fácilmente.

Destreyf
fuente
1

Si obtiene json de la base de datos, coloque

mysqli_set_charset($con, "utf8");

después de definir el enlace de conexión $ con

TomoMiha
fuente
Gracias TomoMiha. Esto es exactamente lo que se adapta a todos mis problemas con MySQL que contiene caracteres especiales y cuando json_decode lo convierte, ese campo en particular se
obtiene
1

En mi caso, se debe a la comilla simple en la cadena JSON.

El formato JSON solo acepta comillas dobles para claves y valores de cadena.

Ejemplo:

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

Tengo esto confundido debido a la sintaxis de Javascript. En Javascript, por supuesto, podemos hacer así:

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

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

pero más tarde, cuando convierta esos objetos en una cadena JSON:

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

Resolví este problema imprimiendo el JSON y luego verificando la fuente de la página (CTRL / CMD + U):

print_r(file_get_contents($url));

Resultó que había una <pre>etiqueta al final .

Jeffrey Roosendaal
fuente
0

deberías asegurarte estos puntos

1. su cadena json no tiene caracteres desconocidos

2. la cadena json se puede ver desde el visor json en línea (puede buscar en google como visor o analizador en línea para json) debería verse sin ningún error

3. su cadena no tiene entidades html, debe ser texto sin formato / cadena

para la explicación del punto 3

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

para (eliminar la función htmlentities ())

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

Para mí, tuve que desactivar el error_reporting para que json_decode () funcione correctamente. Suena extraño, pero cierto en mi caso. Porque hay un aviso impreso entre la cadena JSON que estoy tratando de decodificar.

shasi kanth
fuente
0

Lo más importante que debe recordar, cuando obtiene un resultado NULL de datos JSON que es válido es usar el siguiente comando:

json_last_error_msg();

Es decir.

var_dump(json_last_error_msg());
string(53) "Control character error, possibly incorrectly encoded"

Luego arregla eso con:

$new_json = preg_replace('/[[:cntrl:]]/', '', $json);
Conceder
fuente
0

Entonces, html_entity_decode () funcionó para mí. Por favor intente esto.

$input = file_get_contents("php://input");
$input = html_entity_decode($input);
$event_json = json_decode($input,true);
Suman Deol
fuente
-5
<?php 
$json_url = "http://api.testmagazine.com/test.php?type=menu";
$json = file_get_contents($json_url);
$json=str_replace('},

]',"}

]",$json);
$data = json_decode($json);

echo "<pre>";
print_r($data);
echo "</pre>";
?>
usuario2648057
fuente