Pretty-Printing JSON with PHP

后端 未结 24 1837
一向
一向 2020-11-22 02:03

I\'m building a PHP script that feeds JSON data to another script. My script builds data into a large associative array, and then outputs the data using json_encode

24条回答
  •  抹茶落季
    2020-11-22 03:08

    I took the code from Composer : https://github.com/composer/composer/blob/master/src/Composer/Json/JsonFile.php and nicejson : https://github.com/GerHobbelt/nicejson-php/blob/master/nicejson.php Composer code is good because it updates fluently from 5.3 to 5.4 but it only encodes object whereas nicejson takes json strings, so i merged them. The code can be used to format json string and/or encode objects, i'm currently using it in a Drupal module.

    if (!defined('JSON_UNESCAPED_SLASHES'))
        define('JSON_UNESCAPED_SLASHES', 64);
    if (!defined('JSON_PRETTY_PRINT'))
        define('JSON_PRETTY_PRINT', 128);
    if (!defined('JSON_UNESCAPED_UNICODE'))
        define('JSON_UNESCAPED_UNICODE', 256);
    
    function _json_encode($data, $options = 448)
    {
        if (version_compare(PHP_VERSION, '5.4', '>='))
        {
            return json_encode($data, $options);
        }
    
        return _json_format(json_encode($data), $options);
    }
    
    function _pretty_print_json($json)
    {
        return _json_format($json, JSON_PRETTY_PRINT);
    }
    
    function _json_format($json, $options = 448)
    {
        $prettyPrint = (bool) ($options & JSON_PRETTY_PRINT);
        $unescapeUnicode = (bool) ($options & JSON_UNESCAPED_UNICODE);
        $unescapeSlashes = (bool) ($options & JSON_UNESCAPED_SLASHES);
    
        if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes)
        {
            return $json;
        }
    
        $result = '';
        $pos = 0;
        $strLen = strlen($json);
        $indentStr = ' ';
        $newLine = "\n";
        $outOfQuotes = true;
        $buffer = '';
        $noescape = true;
    
        for ($i = 0; $i < $strLen; $i++)
        {
            // Grab the next character in the string
            $char = substr($json, $i, 1);
    
            // Are we inside a quoted string?
            if ('"' === $char && $noescape)
            {
                $outOfQuotes = !$outOfQuotes;
            }
    
            if (!$outOfQuotes)
            {
                $buffer .= $char;
                $noescape = '\\' === $char ? !$noescape : true;
                continue;
            }
            elseif ('' !== $buffer)
            {
                if ($unescapeSlashes)
                {
                    $buffer = str_replace('\\/', '/', $buffer);
                }
    
                if ($unescapeUnicode && function_exists('mb_convert_encoding'))
                {
                    // http://stackoverflow.com/questions/2934563/how-to-decode-unicode-escape-sequences-like-u00ed-to-proper-utf-8-encoded-cha
                    $buffer = preg_replace_callback('/\\\\u([0-9a-f]{4})/i',
                        function ($match)
                        {
                            return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UCS-2BE');
                        }, $buffer);
                } 
    
                $result .= $buffer . $char;
                $buffer = '';
                continue;
            }
            elseif(false !== strpos(" \t\r\n", $char))
            {
                continue;
            }
    
            if (':' === $char)
            {
                // Add a space after the : character
                $char .= ' ';
            }
            elseif (('}' === $char || ']' === $char))
            {
                $pos--;
                $prevChar = substr($json, $i - 1, 1);
    
                if ('{' !== $prevChar && '[' !== $prevChar)
                {
                    // If this character is the end of an element,
                    // output a new line and indent the next line
                    $result .= $newLine;
                    for ($j = 0; $j < $pos; $j++)
                    {
                        $result .= $indentStr;
                    }
                }
                else
                {
                    // Collapse empty {} and []
                    $result = rtrim($result) . "\n\n" . $indentStr;
                }
            }
    
            $result .= $char;
    
            // If the last character was the beginning of an element,
            // output a new line and indent the next line
            if (',' === $char || '{' === $char || '[' === $char)
            {
                $result .= $newLine;
    
                if ('{' === $char || '[' === $char)
                {
                    $pos++;
                }
    
                for ($j = 0; $j < $pos; $j++)
                {
                    $result .= $indentStr;
                }
            }
        }
        // If buffer not empty after formating we have an unclosed quote
        if (strlen($buffer) > 0)
        {
            //json is incorrectly formatted
            $result = false;
        }
    
        return $result;
    }
    

提交回复
热议问题