JsonFormatter.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Json;
  12. /**
  13. * Formats json strings used for php < 5.4 because the json_encode doesn't
  14. * supports the flags JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
  15. * in these versions
  16. *
  17. * @author Konstantin Kudryashiv <ever.zet@gmail.com>
  18. * @author Jordi Boggiano <j.boggiano@seld.be>
  19. */
  20. class JsonFormatter
  21. {
  22. /**
  23. *
  24. * This code is based on the function found at:
  25. * http://recursive-design.com/blog/2008/03/11/format-json-with-php/
  26. *
  27. * Originally licensed under MIT by Dave Perrett <mail@recursive-design.com>
  28. *
  29. *
  30. * @param string $json
  31. * @param bool $unescapeUnicode Un escape unicode
  32. * @param bool $unescapeSlashes Un escape slashes
  33. * @return string
  34. */
  35. public static function format($json, $unescapeUnicode, $unescapeSlashes)
  36. {
  37. $result = '';
  38. $pos = 0;
  39. $strLen = strlen($json);
  40. $indentStr = ' ';
  41. $newLine = "\n";
  42. $outOfQuotes = true;
  43. $buffer = '';
  44. $noescape = true;
  45. for ($i = 0; $i < $strLen; $i++) {
  46. // Grab the next character in the string
  47. $char = substr($json, $i, 1);
  48. // Are we inside a quoted string?
  49. if ('"' === $char && $noescape) {
  50. $outOfQuotes = !$outOfQuotes;
  51. }
  52. if (!$outOfQuotes) {
  53. $buffer .= $char;
  54. $noescape = '\\' === $char ? !$noescape : true;
  55. continue;
  56. } elseif ('' !== $buffer) {
  57. if ($unescapeSlashes) {
  58. $buffer = str_replace('\\/', '/', $buffer);
  59. }
  60. if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
  61. // http://stackoverflow.com/questions/2934563/how-to-decode-unicode-escape-sequences-like-u00ed-to-proper-utf-8-encoded-cha
  62. $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function($match) {
  63. $l = strlen($match[1]);
  64. if ($l % 2) {
  65. return str_repeat('\\', $l - 1) . mb_convert_encoding(
  66. pack('H*', $match[2]),
  67. 'UTF-8',
  68. 'UCS-2BE'
  69. );
  70. }
  71. return $match[0];
  72. }, $buffer);
  73. }
  74. $result .= $buffer.$char;
  75. $buffer = '';
  76. continue;
  77. }
  78. if (':' === $char) {
  79. // Add a space after the : character
  80. $char .= ' ';
  81. } elseif (('}' === $char || ']' === $char)) {
  82. $pos--;
  83. $prevChar = substr($json, $i - 1, 1);
  84. if ('{' !== $prevChar && '[' !== $prevChar) {
  85. // If this character is the end of an element,
  86. // output a new line and indent the next line
  87. $result .= $newLine;
  88. for ($j = 0; $j < $pos; $j++) {
  89. $result .= $indentStr;
  90. }
  91. } else {
  92. // Collapse empty {} and []
  93. $result = rtrim($result)."\n\n".$indentStr;
  94. }
  95. }
  96. $result .= $char;
  97. // If the last character was the beginning of an element,
  98. // output a new line and indent the next line
  99. if (',' === $char || '{' === $char || '[' === $char) {
  100. $result .= $newLine;
  101. if ('{' === $char || '[' === $char) {
  102. $pos++;
  103. }
  104. for ($j = 0; $j < $pos; $j++) {
  105. $result .= $indentStr;
  106. }
  107. }
  108. }
  109. return $result;
  110. }
  111. }