json_encode devuelve NULL?

119

Por alguna razón, la "descripción" del artículo vuelve NULLcon el siguiente código:

<?php
include('db.php');

$result = mysql_query('SELECT * FROM `staff` ORDER BY `id` DESC LIMIT 2') or die(mysql_error());
$rows = array();
while($row = mysql_fetch_assoc($result)){
    $rows[] = $row;
}

echo json_encode($rows);
?>

Aquí está el esquema de mi base de datos:

CREATE TABLE `staff` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` longtext COLLATE utf8_unicode_ci,
  `description` longtext COLLATE utf8_unicode_ci,
  `icon` longtext COLLATE utf8_unicode_ci,
  `date` longtext COLLATE utf8_unicode_ci,
  `company` longtext COLLATE utf8_unicode_ci,
  `companyurl` longtext COLLATE utf8_unicode_ci,
  `appurl` longtext COLLATE utf8_unicode_ci,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Esto es lo que se repite en la página:

[{"id":"4","name":"Noter 2","description":null,"icon":"http:\/\/images.apple.com\/webapps\/productivity\/images\/noter2_20091223182720-thumb.jpg","date":"1262032317","company":"dBelement, LLC","companyurl":"http:\/\/dbelement.com\/","appurl":"http:\/\/noter2.dbelement.com"},{"id":"3","name":"Noter 2","description":null,"icon":"http:\/\/images.apple.com\/webapps\/productivity\/images\/noter2_20091223182720-thumb.jpg","date":"1262032317","company":"dBelement, LLC","companyurl":"http:\/\/dbelement.com\/","appurl":"http:\/\/noter2.dbelement.com"}]

¿Algunas ideas?

Tarnfeld
fuente
Pongamos las claves de la matriz entre comillas, en primer lugar.
Joost
¿Podría proporcionar información sobre el esquema de su tabla de "personal"? ¿Hay una columna llamada descripción?
mopoke el
¿Todos estos campos se harán eco si simplemente hago un eco $r['description']fuera de la declaración for ()?
Tarnfeld
O quizás ayudaría algún contenido de ejemplo de $ r ['descripción']. ¿Qué tipo de datos es?
mopoke el
¿Podrías hacer una captura de pantalla de la base de datos shema? ;-)
streetparade

Respuestas:

256

Apuesto a que está recuperando datos en una codificación que no es utf8: intente poner mysql_query('SET CHARACTER SET utf8')antes de su SELECTconsulta.

ntd
fuente
5
hola, esta respuesta me salvó la vida, gracias. Yo estaba teniendo el mismo problema aquí. Tenía valores con caracteres no utf8 como "Validação de Formulários". Sé que esta pregunta es un poco vieja ahora, ¡pero eso es lo maravilloso de Internet!
fabio
7
mysql_set_charset es mejor por razones de seguridad desde PHP 5.2.3. Consulte php.net/manual/en/function.mysql-set-charset.php para obtener más detalles.
masakielastic
3
Porque UTF8 es la lengua franca en la web. En lugar de saturar la API con parámetros adicionales y gastos generales, PHP (correctamente) usa la codificación más común, dejándote la carga de la conversión si usas una codificación poco común (o casi muerta, como en tu caso).
ntd
1
La forma recomendada de hacer esto ahora ha cambiado. Intenté editar esta respuesta para incluir un enlace pero fue rechazado. La forma correcta está en mi respuesta a continuación.
bejs
1
@VeeK no es suficiente tener tus campos almacenados en UTF-8: debes configurar tu servidor para responder a clientes en UTF-8. AFAIK stock mysql y mariadb usan latin1.
ntd
118

Si tiene al menos PHP 5.5, puede usar json_last_error_msg () , que devolverá una cadena que describe el problema.

Si no tiene 5.5, pero está en / por encima de 5.3, puede usar json_last_error () para ver cuál es el problema.

Devolverá un número entero, que puede usar para identificar el problema en la documentación de la función . Actualmente (2012.01.19), los identificadores son:

0 = JSON_ERROR_NONE
1 = JSON_ERROR_DEPTH
2 = JSON_ERROR_STATE_MISMATCH
3 = JSON_ERROR_CTRL_CHAR
4 = JSON_ERROR_SYNTAX
5 = JSON_ERROR_UTF8

Estos pueden cambiar en futuras versiones, por lo que es mejor consultar el manual.

Si está por debajo de 5.3, no tiene suerte, no hay forma de preguntar cuál fue el error.

K. Norbert
fuente
18

La respuesta de ntd no resolvió mi problema. Para aquellos en la misma situación, así es como finalmente manejé este error: Simplemente use utf8_encode cada uno de sus resultados.

while($row = mysql_fetch_assoc($result)){
    $rows[] = array_map('utf8_encode', $row);
}

¡Espero eso ayude!

Pablo Abdelhay
fuente
También tuve problemas de codificación. con codificación mixta. solución que encontré: stackoverflow.com/a/3521396/776345
Paschalis
9

Hace unos días tengo el MISMO problema con 1 mesa.

Primero intente:

echo json_encode($rows);
echo json_last_error();  // returns 5 ?

Si la última línea devuelve 5, el problema está en sus datos . Lo sé, sus tablas están en UTF-8, pero no se ingresaron datos . Por ejemplo, la entrada estaba en un archivo txt, pero se creó en una máquina Win con una codificación estúpida (en mi caso, Win-1250 = CP1250) y estos datos se ingresaron en la base de datos.

¿Solución? Busque nuevos datos (excel, página web), edite el archivo txt de origen a través de PSPad (o cualquier otra cosa), cambie la codificación a UTF-8 , elimine todas las filas y ahora coloque los datos del original. Salvar. Entrar en DB .

También puede cambiar la codificación a utf-8 y luego cambiar todas las filas manualmente (proporcione cols con caracteres especiales - desc, ...). Bueno para esclavos ...

Ivo Urbanek
fuente
o use la JSON_PARTIAL_OUTPUT_ON_ERRORopción para ver el problema (por ejemplo, el campo con UTF8 será nulo).
Peter Krauss
6

Debe pasar una cadena codificada en utf8 en json_encode. Puede usar utf8_encodey array_map()funcionar como se muestra a continuación:

<?php
    $encoded_rows = array_map('utf8_encode', $rows);
    echo json_encode($encoded_rows);
?>
koder
fuente
4

AHHH !!! Esto se ve tan mal que me duele la cabeza. Prueba algo más parecido a esto ...

<?php
include('db.php');

$result = mysql_query('SELECT `id`, `name`, `description`, `icon` FROM `staff` ORDER BY `id` DESC LIMIT 20') or die(mysql_error());
$rows = array();
while($row = mysql_fetch_assoc($result)){
    $rows[] = $row;
}

echo json_encode($rows);
?>
  • Cuando la iteración en mysql_num_rowsque debe utilizar <no <=. También debe almacenar en caché este valor (guardarlo en una variable) en lugar de que vuelva a contar cada ciclo. Quién sabe lo que está haciendo debajo del capó ... (podría ser eficiente, no estoy muy seguro)
  • No necesitas copiar cada valor explícitamente así ... solo te lo estás haciendo más difícil. Si la consulta devuelve más valores de los que ha enumerado allí, enumere solo los que desea en su SQL.
  • mysql_fetch_arraydevuelve los valores por keyy por int. No estás usando los índices, así que no los busques.

Si esto realmente es un problema json_encode, entonces podría sugerir reemplazar el cuerpo del bucle con algo como

$rows[] = array_map('htmlentities',$row);

Perhpas hay algunos caracteres especiales que están arruinando las cosas ...

mpen
fuente
[{"id": "4", "nombre": "Noter 2", "descripción": nulo, "icono": "http: \ / \ / images.apple.com \ / webapps \ / productividad \ / images \ /noter2_20091223182720-thumb.jpg "," fecha ":" 1262032317 "," empresa ":" dBelement, LLC "," companyurl ":" http: \ / \ / dbelement.com \ / "," appurl ":" http: \ / \ / noter2.dbelement.com "}, {" id ":" 3 "," nombre ":" Noter 2 "," descripción ": nulo," icono ":" http: \ / \ / imágenes .apple.com \ / webapps \ / productividad \ / images \ /noter2_20091223182720-thumb.jpg "," fecha ":" 1262032317 "," empresa ":" dBelement, LLC "," empresaurl ":" http: \ / \ /dbelement.com\/","appurl":"http:\/\/noter2.dbelement.com "
tarnfeld
@tarnfield: Bueno, ¿es eso lo que quieres o no? Oh ... tienes información adicional ahí ... aquí ... déjame arreglar eso por ti.
mpen
Sí, "descripción" regresanull
Tarnfeld
Si la descripción está regresando null, probablemente lo sea null . Pruebe echo $row['description'].'<br/>';en ese bucle y vea lo que dice.
mpen
1
hola, esta respuesta me salvó la vida, gracias. Yo estaba teniendo el mismo problema aquí. Tenía valores con caracteres no utf8 como "Validação de Formulários". Sé que esta pregunta es un poco vieja ahora, ¡pero eso es lo maravilloso de Internet!
fabio
3

Para cualquiera que use PDO, la solución es similar a la respuesta de ntd .

Desde la página de construcción PHP PDO :: __ , como comentario del usuario Kiipa en live dot com :

Para obtener el juego de caracteres UTF-8, puede especificarlo en el DSN.

$ enlace = nuevo PDO ("mysql: host = localhost; dbname = DB; charset = UTF8 ");

MichaelS
fuente
0

Para mí, un problema en el que json_encode devolvería la codificación nula de una entidad fue porque mi implementación jsonSerialize obtuvo objetos completos para entidades relacionadas; Resolví el problema asegurándome de obtener el ID de la entidad relacionada / asociada y llamé -> toArray () cuando había más de una entidad asociada con el objeto para ser serializado json. Tenga en cuenta que estoy hablando de casos en los que se trata implements JsonSerializablede entidades.

Víctor S
fuente
-4

Tuve el mismo problema y la solución fue usar mi propia función en lugar de json_encode()

echo '["' . implode('","', $row) . '"]';
Laci
fuente