json_encode() en PHP: serializar arrays y objetos con todos sus flags

json_encode() convierte cualquier valor PHP (arrays, objetos, scalares) en una cadena JSON válida. En su uso básico es sencilla, pero su segundo parámetro de flags permite ajustar la salida para casos habituales: depuración, APIs, URLs, manejo de errores.

Uso básico

<?php
$datos = [
    'nombre' => 'Ana García',
    'edad'   => 28,
    'activa' => true,
    'puntos' => null,
    'tags'   => ['php', 'backend'],
];

echo json_encode($datos);
// {"nombre":"Ana García","edad":28,"activa":true,"puntos":null,"tags":["php","backend"]}
?>

JSON_PRETTY_PRINT: salida formateada

<?php
$datos = ['nombre' => 'Ana', 'edad' => 28, 'ciudad' => 'Madrid'];

echo json_encode($datos, JSON_PRETTY_PRINT);
/*
{
    "nombre": "Ana",
    "edad": 28,
    "ciudad": "Madrid"
}
*/
?>

JSON_UNESCAPED_UNICODE: caracteres UTF-8 sin escapes

Por defecto, json_encode() escapa los caracteres no ASCII con la secuencia uXXXX. El flag JSON_UNESCAPED_UNICODE los emite tal cual, lo que produce JSON más legible y compacto:

<?php
$texto = ['mensaje' => 'Bienvenido, José. ¡Hola España!'];

// Sin flag: escapa caracteres UTF-8
echo json_encode($texto);
// {"mensaje":"Bienvenido, José. ¡Hola España!"}

// Con JSON_UNESCAPED_UNICODE: más legible
echo json_encode($texto, JSON_UNESCAPED_UNICODE);
// {"mensaje":"Bienvenido, José. ¡Hola España!"}
?>

JSON_UNESCAPED_SLASHES: URLs sin backslashes

<?php
$enlace = ['url' => 'https://programacion.net/articulo/php_3500'];

// Sin flag: las barras se escapan con backslash
echo json_encode($enlace);
// {"url":"https://programacion.net/articulo/php_3500"}

// Con JSON_UNESCAPED_SLASHES: más limpio
echo json_encode($enlace, JSON_UNESCAPED_SLASHES);
// {"url":"https://programacion.net/articulo/php_3500"}
?>

Combinar varios flags con el operador |

<?php
$api = [
    'url'      => 'https://api.ejemplo.com/v1/usuarios',
    'mensaje'  => 'Operación completada. ¡Éxito!',
    'total'    => 42,
    'paginas'  => ['anterior' => null, 'siguiente' => 'https://api.ejemplo.com/v1/usuarios?p=2'],
];

$flags = JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
echo json_encode($api, $flags);
?>

JSON_THROW_ON_ERROR: gestión de errores con excepciones

Antes de PHP 7.3, había que comprobar manualmente el valor de retorno y llamar a json_last_error(). Con JSON_THROW_ON_ERROR, cualquier fallo lanza una JsonException:

<?php
// Valor que no se puede serializar: recurso de fichero
$fh = fopen('/tmp/test.txt', 'w');

try {
    $json = json_encode(['fh' => $fh], JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    echo 'Error al serializar: ' . $e->getMessage();
    // Error al serializar: Type is not supported
}

// Sin JSON_THROW_ON_ERROR: json_encode devuelve false silenciosamente
$json = json_encode(['fh' => $fh]);
var_dump($json); // bool(false)
?>

La interfaz JsonSerializable

Para controlar cómo se serializa un objeto, implementa la interfaz JsonSerializable:

<?php
class Usuario implements JsonSerializable
{
    public function __construct(
        private string $nombre,
        private string $email,
        private string $passwordHash  // no debe aparecer en el JSON
    ) {}

    public function jsonSerialize(): mixed
    {
        return [
            'nombre' => $this->nombre,
            'email'  => $this->email,
            // passwordHash excluida intencionadamente
        ];
    }
}

$usuario = new Usuario('Ana García', '[email protected]', 'hash_secreto');
echo json_encode($usuario, JSON_UNESCAPED_UNICODE);
// {"nombre":"Ana García","email":"[email protected]"}
?>

La trampa de arrays filtrados que se convierten en objetos

Si filtras un array con array_filter() y las claves no son consecutivas, PHP lo trata como array asociativo y JSON lo serializa como objeto en lugar de array:

<?php
$original = [0, 1, 2, 3, 4];
$filtrado = array_filter($original, fn($n) => $n % 2 === 0);

var_dump(array_keys($filtrado)); // [0, 2, 4]  ? claves no consecutivas

echo json_encode($filtrado);
// {"0":0,"2":2,"4":4}  ? serializado como objeto, no como array

// Solución: reindexar con array_values()
echo json_encode(array_values($filtrado));
// [0,2,4]  ? array correcto
?>

La documentación oficial de json_encode() lista todos los flags disponibles, incluyendo JSON_NUMERIC_CHECK, JSON_FORCE_OBJECT y JSON_HEX_* para casos más específicos.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP