Estoy tratando de manejar datos json incorrectos cuando se analizan a través de json_decode(). Estoy usando el siguiente script:
if(!json_decode($_POST)) {
echo "bad json data!";
exit;
}
Si $_POST es igual a:
'{ bar: "baz" }'
Luego, json_decode maneja bien el error y escupe “¡datos json incorrectos!”; Sin embargo, si configuro $_POST en algo como “datos no válidos”, me da:
Warning: json_decode() expects parameter 1 to be string, array given in C:\server\www\myserver.dev\public_html\rivrUI\public_home\index.php on line 6
bad json data!
¿Necesito escribir un script personalizado para detectar datos json válidos, o hay alguna otra forma ingeniosa de detectar esto?
Aquí hay un par de cosas sobre json_decode
:
- devuelve los datos, o
null
cuando hay un error
- tambien puede volver
null
cuando no hay error: cuando la cadena JSON contiene null
- genera una advertencia donde hay una advertencia, una advertencia que quieres hacer desaparecer.
Para resolver el problema de las advertencias, una solución sería usar el @
operador (No recomiendo usarlo a menudo, ya que hace que la depuración sea mucho más difícil… Pero aquí, no hay muchas opciones) :
$_POST = array(
'bad data'
);
$data = @json_decode($_POST);
Entonces tendrías que probar si $data
es null
— y, para evitar el caso en que json_decode
devoluciones null
por null
en la cadena JSON, puede verificar json_last_error
cual (citando) :
Devuelve el último error (si lo hay) que se produjo en el último análisis de JSON.
Lo que significa que tendrías que usar algún código como el siguiente:
if ($data === null
&& json_last_error() !== JSON_ERROR_NONE) {
echo "incorrect data";
}
También puedes usar json_last_error: http://php.net/manual/en/function.json-ultimo-error.php
que como documentación dice:
Devuelve el último error (si lo hubo) ocurrido durante la última codificación/descodificación JSON.
Aquí hay un ejemplo
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;
}

dtar
Desde PHP 7.3la función json_decode aceptará una nueva opción JSON_THROW_ON_ERROR que permitirá que json_decode genere una excepción en lugar de devolver un valor nulo en caso de error.
Ejemplo:
try {
json_decode("{", false, 512, JSON_THROW_ON_ERROR);
}
catch (\JsonException $exception) {
echo $exception->getMessage(); // displays "Syntax error"
}

corredor de klompen
Me rompí la cabeza por un error de sintaxis json en lo que parecía ser un json perfecto: {"test1":"car", "test2":"auto"}
de una cadena codificada de url.
Pero en mi caso, algo de lo anterior estaba codificado en html, como agregar html_entity_decode($string)
Hizo el truco.
$ft = json_decode(html_entity_decode(urldecode(filter_input(INPUT_GET, 'ft', FILTER_SANITIZE_STRING))));
Con suerte, esto le ahorrará tiempo a alguien más.
Así es como Guzzle maneja json
/**
* Parse the JSON response body and return an array
*
* @return array|string|int|bool|float
* @throws RuntimeException if the response body is not in JSON format
*/
public function json()
{
$data = json_decode((string) $this->body, true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new RuntimeException('Unable to parse response body into JSON: ' . json_last_error());
}
return $data === null ? array() : $data;
}

Zet
Acabo de pasar una hora revisando todas las soluciones posibles en esta página. Me tomé la libertad de recopilar todas estas posibles soluciones en una funcionpara que sea más rápido y fácil de probar y depurar.
Espero que pueda ser de utilidad para alguien más.
<?php
/**
* Decontaminate text
*
* Primary sources:
* - https://stackoverflow.com/questions/17219916/json-decode-returns-json-error-syntax-but-online-formatter-says-the-json-is-ok
* - https://stackoverflow.com/questions/2348152/detect-bad-json-data-in-php-json-decode
*/
function decontaminate_text(
$text,
$remove_tags = true,
$remove_line_breaks = true,
$remove_BOM = true,
$ensure_utf8_encoding = true,
$ensure_quotes_are_properly_displayed = true,
$decode_html_entities = true
){
if ( '' != $text && is_string( $text ) ) {
$text = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $text );
$text = str_replace(']]>', ']]>', $text);
if( $remove_tags ){
// Which tags to allow (none!)
// $text = strip_tags($text, '<p>,<strong>,<span>,<a>');
$text = strip_tags($text, '');
}
if( $remove_line_breaks ){
$text = preg_replace('/[\r\n\t ]+/', ' ', $text);
$text = trim( $text );
}
if( $remove_BOM ){
// Source: https://stackoverflow.com/a/31594983/1766219
if( 0 === strpos( bin2hex( $text ), 'efbbbf' ) ){
$text = substr( $text, 3 );
}
}
if( $ensure_utf8_encoding ){
// Check if UTF8-encoding
if( utf8_encode( utf8_decode( $text ) ) != $text ){
$text = mb_convert_encoding( $text, 'utf-8', 'utf-8' );
}
}
if( $ensure_quotes_are_properly_displayed ){
$text = str_replace('"', '"', $text);
}
if( $decode_html_entities ){
$text = html_entity_decode( $text );
}
/**
* Other things to try
* - the chr-function: https://stackoverflow.com/a/20845642/1766219
* - stripslashes (THIS ONE BROKE MY JSON DECODING, AFTER IT STARTED WORKING, THOUGH): https://stackoverflow.com/a/28540745/1766219
* - This (improved?) JSON-decoder didn't help me, but it sure looks fancy: https://stackoverflow.com/a/43694325/1766219
*/
}
return $text;
}
// Example use
$text = decontaminate_text( $text );
// $text = decontaminate_text( $text, false ); // Debug attempt 1
// $text = decontaminate_text( $text, false, false ); // Debug attempt 2
// $text = decontaminate_text( $text, false, false, false ); // Debug attempt 3
$decoded_text = json_decode( $text, true );
echo json_last_error_msg() . ' - ' . json_last_error();
?>
Lo mantendré aquí: https://github.com/zethodderskov/decontaminate-text-in-php/blob/master/decontaminate-text-preparing-it-for-json-decode.php

Tomáš Fejfar
/**
*
* custom json_decode
* handle json_decode errors
*
* @param type $json_text
* @return type
*/
public static function custom_json_decode($json_text) {
$decoded_array = json_decode($json_text, TRUE);
switch (json_last_error()) {
case JSON_ERROR_NONE:
return array(
"status" => 0,
"value" => $decoded_array
);
case JSON_ERROR_DEPTH:
return array(
"status" => 1,
"value" => 'Maximum stack depth exceeded'
);
case JSON_ERROR_STATE_MISMATCH:
return array(
"status" => 1,
"value" => 'Underflow or the modes mismatch'
);
case JSON_ERROR_CTRL_CHAR:
return array(
"status" => 1,
"value" => 'Unexpected control character found'
);
case JSON_ERROR_SYNTAX:
return array(
"status" => 1,
"value" => 'Syntax error, malformed JSON'
);
case JSON_ERROR_UTF8:
return array(
"status" => 1,
"value" => 'Malformed UTF-8 characters, possibly incorrectly encoded'
);
default:
return array(
"status" => 1,
"value" => 'Unknown error'
);
}
}
$_POST
es siempre una matriz que contiene el x-www-form-urlencoded parámetros pasados a través de POST. ¿Cómo envía sus datos a su script PHP?– Gumbo
27 de febrero de 2010 a las 16:58
Las funciones json incluidas en PHP no son de mucha ayuda. Tienen muchos problemas. Echa un vistazo a json.org encontrar una buena biblioteca.
– whiskysierra
27 de febrero de 2010 a las 17:02