Formatage json en PHP

PHP possède des méthodes pour lire (json_decode) ou encoder (json_encode) des objets json. La chaîne de caractères retournée par cette dernière méthode est malheureusement illisible car sans indentation. Et comme l'un des intérêts du json, c'est justement de pouvoir être lu facilement par un humain, voici comment corriger cela...

En fait, une option JSON_PRETTY_PRINT existe pour la méthode json_encode, mais elle n'est disponible qu'à partir de PHP 5.4. Donc, pour ceuses qui sont encore bloqués comme moi à la version 5.3.x, une fonction extraite du framework Zend à peine modifiée peut faire l'affaire :

/**
 *  Formater une chaîne json pour qu'elle soit lisible.
 *  From Zend_Json::prettyPrint
 *  @param {String} $json Chaîne au format json
 *  @return {String} Chaîne json formatée.
 */
public static function prettyJson($json) {
    $tokens = preg_split('|([\{\}\]\[,])|', $json, -1, PREG_SPLIT_DELIM_CAPTURE);
    $result = '';
    $indent = 0;
    $ind    = '    ';
    $lineBreak = "\n";
    $inLiteral = false;
    foreach($tokens as $token) {
        if ($token == '') {
            continue;
        }
        $prefix = str_repeat($ind, $indent);
        if (!$inLiteral && ($token == '{' || $token == '[')) {
            $indent++;
            if (($result != '') && ($result[(strlen($result)-1)] == $lineBreak)) {
                $result .= $prefix;
            }
            $result .= $token . $lineBreak;
        } elseif (!$inLiteral && ($token == '}' || $token == ']')) {
            $indent--;
            $prefix = str_repeat($ind, $indent);
            $result .= $lineBreak . $prefix . $token;
        } elseif (!$inLiteral && $token == ',') {
            $result .= $token . $lineBreak;
        } else {
            $result .= ( $inLiteral ? '' : $prefix ) . $token;
            // Count # of unescaped double-quotes in token, subtract # of
            // escaped double-quotes and if the result is odd then we are 
            // inside a string literal
            if ((substr_count($token, "\"")-substr_count($token, "\\\"")) % 2 != 0) {
                $inLiteral = !$inLiteral;
            }
        }
    }
    return $result;
}
Fonction de formatage d'une chaîne de caractères représentant un objet json, tirée du framework Zend.

L'opération a évidemment un coût, par le traitement supplémentaire qu'elle implique mais aussi par la taille de la chaîne résultante. Après quelques tests, il s'avère que le poids de mes fichiers json a augmenté de 45% environ. Loin d'être négligeable donc. A utiliser uniquement pour des fichiers que l'on consulte directement (surtout que des chaînes trop longues font méchamment ramer Gedit).

ACHOUR, Mehdi ; BETZ, Friedhelm ; DOVGAL, Antony, et al.. Manuel PHP. PHP.net, . json_encode

ZEND TECHNOLOGIES. Programmer's Reference Guide. framework.zend.com, . Zend_Json > basic usage