Javascript

Manipuler du JSON en PHP

Publié dans PHP | Marqué avec , , ,
Share

Pour manipuler du JSON en PHP, il y a 2-3 petites choses à savoir. L’encodage, décodage c’est la première étape. Ensuite on peut s’amuser à gérer des cas bizarres et les erreurs. Et après… après on peut s’amuser avec des schémas si jamais l’envie nous prend.

Encodage / Décodage

Tout d’abord, les méthodes qui font l’essentiel du travail :

  • json_decode: transforme une chaîne de caractères JSON en variable PHP
  • json_encode: transforme une variable PHP en chaîne de caractères JSON

Cependant, il faut garder en tête que ces méthodes ne travaillent qu’avec de l’UTF-8. Allez savoir pourquoi alors que c’est plutôt l’inverse en PHP généralement… mais bref. Du coup, un petit coup de utf8_encode / utf8_decode avant d’utiliser json_decode sur autre chose que de l’UTF-8. Même topo pour json_encode.
La documentation PHP nous fournit quelques autres informations intéressantes, par exemple au sujet de la manière d’accéder à un objet contenant un trait d’union en PHP ($myObject->{'param-etre'}).

Autoriser une syntaxe moins rigoureuse

Il m’arrive assez souvent d’avoir des fichiers de configurations en JSON. Je trouve ça lisible et très souple. L’ennui, c’est que j’aimerai pouvoir ajouter des commentaires, et ne pas avoir à farfouiller mon fichier de config si, par mégarde, j’ai ajouté une virgule de trop à la fin d’un objet. Ce dernier point peut vite s’avérer pénible.

object specification

La méthode ci-dessous permet d’autoriser une syntaxe moins rigoureuse en prenant soin de modifier les petites erreurs qui ont pu être commises.

/**
 * Clean a string
 * * Remove comments ("//" and "/*")
 * * Add first and last braces ("{" and "}") if missing
 * * Remove unauthorized commas
 */
function cleanJsonString($data) {
	$data = trim($data);
	$data = preg_replace('!\s*//[^"]*\n!U', '\n', $data);
	$data = preg_replace('!/\*[^"]*\*/!U', '', $data);
	$data = !startsWith('{', $data) ? '{'.$data : $data;
	$data = !endsWith('}', $data) ? $data.'}' : $data;
	$data = preg_replace('!,(\s*[}\]])!U', '$1', $data);
	return $data;
}

Avec les méthodes « startsWith » et « endsWidths » :

function startsWith($needle, $haystack) {
    return !strncmp($haystack, $needle, strlen($needle));
}

function endsWith($needle, $haystack) {
    $length = strlen($needle);
    if ($length == 0)
        return true;
    return (substr($haystack, -$length) === $needle);
}

Gestion des codes d’erreur

La méthode json_last_error nous permet de connaître le code d’erreur du dernier encodage ou décodage JSON. Super ! Mais il peut être ennuyant de se taper la doc pour savoir à quoi cela correspond.
La fonction suivante retourne un message d’erreur en français à la place du code d’erreur.

/**
 * Retourne la signification de la dernière erreur 
 * d'encodage / décodage.
 * En français.
 */
function getJsonLastError() {
	switch (json_last_error()) {
		case JSON_ERROR_NONE:
			return 'Aucune erreur';
		break;
		case JSON_ERROR_DEPTH:
			return 'Profondeur maximale atteinte';
		break;
		case JSON_ERROR_STATE_MISMATCH:
			return 'Inadéquation des modes ou underflow';
		break;
		case JSON_ERROR_CTRL_CHAR:
			return 'Erreur lors du contrôle des caractères';
		break;
		case JSON_ERROR_SYNTAX:
			return 'Erreur de syntaxe ; JSON malformé';
		break;
		case JSON_ERROR_UTF8:
			return 'Caractères UTF-8 malformés, probablement une erreur d\'encodage';
		break;
	}
	return 'Erreur inconnue';
}

La documentation PHP propose une autre solution (adaptée par mes soins), renvoyant directement le code d’erreur en version texte, ce qui est généralement suffisant.

/**
 * Retourne la signification de la dernière erreur 
 * d'encodage / décodage.
 */
function getJsonLastError() {
	$lastErrorCode = json_last_error();
	$constants = get_defined_constants(true);
	foreach ($constants["json"] as $name => $code) {
		if ($code == $lastErrorCode) {
			return $name
		}
	}
	return 'Unknown';
}

Si je fais un petit mixe de tout ces bouts de code, on obtient le résultat suivant :

// Un petit coup de clean
$string = cleanJsonString($jsonString);
// Un petit coup de décodage (ajouter utf8_encode si besoin)
$data = json_decode($string);
// Une erreur ?
if (NULL == $data) {
    echo getJsonLastError();
}

Validation avec des schémas JSON

Les schémas XML (XSD) sont bigrement utilisées pour décrire et valider des protocoles, générer du code ou comme base de piles de communication.
L’idée des schémas JSON est de fournir les mêmes possibilités mais avec du JSON. Le JSON est plus simple, moins verbeux et plus facilement manipulable qu’XML, mais il n’en a pas toute les capacités. De même les schémas JSON sont plus simples que les schémas XML, mais moins puissants aussi. D’autant plus que cette notion est encore assez jeune, l’an dernier ce n’était pas encore standardisé, mais ça a l’air bon maintenant. Le site Web JSON Schema décrit la syntaxe et fournit des exemples d’utilisation.
Il existe au moins une implémentation PHP sachant manipuler des schémas : JSON Schema for PHP. ça a l’air plutôt pas mal.

Un exemple d’utilisation ? Composer. Les fichiers de descriptions Composer sont validés à l’aide d’un schéma JSON. Chouette, non ? J’espère avoir l’occasion de manipuler tout cela un de ces jours.

One Response to Manipuler du JSON en PHP

  1. Ping : Corriger une string JSON en Qt 30 minutes par jour

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *