Codificar JSON en PHP
Con json_encode se puede traducir cualquier cosa codificada en UTF-8 (salvo resources) de PHP a un string JSON. Todo salvo arrays puros (éstos en PHP son arrays con un index numérico y ordenado) se convierte en un objeto con keys y values.
Las opciones $options son un bitmask, que permite cambiar la forma en que se codifican los datos. En los siguientes ejemplos no lo vamos a emplear, por lo que se utilizan los valores por defecto.
Empezando con los tipos básicos:
Cómo se traducen los arrays depende del index que se utilice. Puede verse que _jsonencode() traduce los tipos correctamente en el caso de booleano y null.
Los objetos se inspeccionan y sus atributos públicos se convierten. Esto ocurre de forma recursiva, por lo que en el ejemplo anterior los atributos del objeto DateTime también se traducen en JSON. Esta es una forma de transmitir fácilmente fechas en JSON, el lado del cliente podrá tomar el tiempo real y el timezone.
Se puede comprobar que sólo se utilizan los atributos públicos, variables no iniciadas se traducen en null y los closures de un atributo público se codifican como un objeto vacío.
El bitmask $option
Los bitmasks se utilizan para establecer ciertas banderas On y Off en una llamada a una función. Si quieres establecer una opción, simplemente añade la constante como argumento. Si quieres combinar dos o más opciones, combínalas con el operador || o OR.
JSON_FORCE_OBJECT fuerza el array a ser traducido en un objeto y JSON_NUMERIC_CHECK convierte números dentro de strings en números. La lista de bitmasks es esta. Muchos de ellos sirven para tratar con caracteres como <, >, & o "". También hay una constante que sirve para ver los resultados más claros con espacios en blanco, JSON_PRETTY_PRINT (no recomendable en producción ya que añade caracteres innecesarios).
Decodificar JSON en PHP
Decodificar JSON en PHP es tan sencillo como codificar. PHP proporciona la función _jsondecode se encarga de ello. Simplemente pasando un string JSON válido en el método se obtiene un objeto stdClass.
Si lo que quieres es obtener un array asociativo, simplemente hay que poner un segundo parámetro como true:
Si se espera un archivo JSON muy extenso, se puede limitar la profundidad de recursión a un nivel determinado. La función devolverá null y dejará de analizar si el documento es más profundo que el nivel marcado:
El último argumento funciona de la misma forma que en _jsonencode, pero sólo está la opción de JSON_BIGINT_AS_STRING, que convierte bigints en strings.
Manejo de errores y testing
Si el valor JSON no se ha podido analizar o la profundidad de recursión es mayor de la indicada (como en el ejemplo anterior), se obtiene null de json_decode. Esto significa que no surge ninguna excepción directamente de _jsonencode o _jsondecode.
Para el manejo de errores de emplea la función _json_lasterror, que devuelve un integer con un código de error que puede ser uno de los siguientes:
- JSON_ERROR_NONE: No ha habido ningún error.
JSON_ERROR_DEPTH: El máximo nivel de profundidad se ha excedido.
JSON_ERROR_STATE_MISMATCH: JSON inválido o mal formado.
JSON_ERROR_CTRL_CHAR: Error de control de caracteres, posiblemente incorrectamente codificado.
JSON_ERROR_SYNTAX: Error de sintaxis.
JSON_ERROR_UTF8: Caracteres UTF-8 mal formados, posiblemente incorrectamente codificado.
Con dicha información se puede escribir un método helper que proporciona una descripción cuando ocurre un error:
Ahora podemos utilizar la clase: