<?php
final class JsonUtils
{
   /**
* Input an object, returns a json-ized string of said object, pretty-printed
*
* @param (mixed) $obj: The array or object to encode
* @param (int) $indentation: The number of "in front" blanks (difference between levels)
* @param (int) $level: shouldn't be set, define the first level of "blanks"
* @return string JSON formatted output
*/

   public static function prettyJsonEncode($obj, $indentation= 2, $level= 0) {
      switch (gettype($obj)) {
         case 'object':
            $obj = get_object_vars($obj);
         case 'array':
            if (!isset($obj[0])) {
               $arr_out = array();
               foreach ($obj as $key => $val) {
                  $arr_out[] = '"' . addslashes($key) . '": ' . self::json_encode_pretty($val, $indentation, $level + 1);
               }
               return "{\n" . str_repeat(" ", ($level + 1)*$indentation) . implode(",\n".str_repeat(" ", ($level + 1)*$indentation), $arr_out) . "\n" . str_repeat(" ", $level*$indentation) . "}";
            } else {
               $arr_out = array();
               $ct = count($obj);
               for ($j = 0; $j < $ct; $j++) {
                  $arr_out[] = self::json_encode_pretty($obj[$j], $indentation, $level + 1);
               }
               return "[\n" . str_repeat(" ", ($level + 1)*$indentation) . implode(",\n".str_repeat(" ", ($level + 1)*$indentation), $arr_out) . "\n" . str_repeat(" ", $level*$indentation) . "]";
            }
            break;
         case 'NULL':
            return 'null';
            break;
         case 'boolean':
            return $obj ? 'true' : 'false';
            break;
         case 'integer':
         case 'double':
            return $obj;
            break;
         case 'string':
         default:
            $obj = str_replace(array('\\','"',), array('\\\\','\"'), $obj);
            return '"' . $obj . '"';
            break;
      }
   }

   /* easy way to get the error message for the former json_encode PHP function
*/
   public static function getLastJsonError() {
      switch (json_last_error()) {
         case JSON_ERROR_NONE:
            return false;
            break;
         case JSON_ERROR_DEPTH:
            return 'Maximum stack depth exceeded';
            break;
         case JSON_ERROR_STATE_MISMATCH:
            return 'Underflow or the modes mismatch';
            break;
         case JSON_ERROR_CTRL_CHAR:
            return 'Unexpected control character found';
            break;
         case JSON_ERROR_SYNTAX:
            return 'Syntax error, malformed JSON';
            break;
         case JSON_ERROR_UTF8:
            return 'Malformed UTF-8 characters, possibly incorrectly encoded';
            break;
         default:
            return 'Unknown error';
            break;
      }
   }
}
?>