forked from Wavyzz/dolibarr
211 lines
6.8 KiB
PHP
211 lines
6.8 KiB
PHP
<?php
|
|
namespace Luracast\Restler\Format;
|
|
|
|
use Luracast\Restler\Data\Object;
|
|
use Luracast\Restler\RestException;
|
|
|
|
/**
|
|
* Javascript Object Notation Format
|
|
*
|
|
* @category Framework
|
|
* @package Restler
|
|
* @subpackage format
|
|
* @author R.Arul Kumaran <arul@luracast.com>
|
|
* @copyright 2010 Luracast
|
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
|
* @link http://luracast.com/products/restler/
|
|
* @version 3.0.0rc5
|
|
*/
|
|
class JsonFormat extends Format
|
|
{
|
|
/**
|
|
* @var boolean|null shim for json_encode option JSON_PRETTY_PRINT set
|
|
* it to null to use smart defaults
|
|
*/
|
|
public static $prettyPrint = null;
|
|
|
|
/**
|
|
* @var boolean|null shim for json_encode option JSON_UNESCAPED_SLASHES
|
|
* set it to null to use smart defaults
|
|
*/
|
|
public static $unEscapedSlashes = null;
|
|
|
|
/**
|
|
* @var boolean|null shim for json_encode JSON_UNESCAPED_UNICODE set it
|
|
* to null to use smart defaults
|
|
*/
|
|
public static $unEscapedUnicode = null;
|
|
|
|
/**
|
|
* @var boolean|null shim for json_decode JSON_BIGINT_AS_STRING set it to
|
|
* null to
|
|
* use smart defaults
|
|
*/
|
|
public static $bigIntAsString = null;
|
|
|
|
const MIME = 'application/json';
|
|
const EXTENSION = 'json';
|
|
|
|
public function encode($data, $humanReadable = false)
|
|
{
|
|
if (!is_null(self::$prettyPrint)) {
|
|
$humanReadable = self::$prettyPrint;
|
|
}
|
|
if (is_null(self::$unEscapedSlashes)) {
|
|
self::$unEscapedSlashes = $humanReadable;
|
|
}
|
|
if (is_null(self::$unEscapedUnicode)) {
|
|
self::$unEscapedUnicode = $this->charset == 'utf-8';
|
|
}
|
|
$options = 0;
|
|
if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) // PHP >= 5.4
|
|
|| PHP_MAJOR_VERSION > 5 // PHP >= 6.0
|
|
) {
|
|
if ($humanReadable) $options |= JSON_PRETTY_PRINT;
|
|
if (self::$unEscapedSlashes) $options |= JSON_UNESCAPED_SLASHES;
|
|
if (self::$bigIntAsString) $options |= JSON_BIGINT_AS_STRING;
|
|
if (self::$unEscapedUnicode) $options |= JSON_UNESCAPED_UNICODE;
|
|
return json_encode(
|
|
Object::toArray($data, true), $options
|
|
);
|
|
}
|
|
|
|
$result = json_encode(Object::toArray($data, true));
|
|
if ($humanReadable) $result = $this->formatJson($result);
|
|
if (self::$unEscapedUnicode) {
|
|
$result = preg_replace_callback('/\\\u(\w\w\w\w)/',
|
|
function($matches)
|
|
{
|
|
if (function_exists('mb_convert_encoding'))
|
|
{
|
|
return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UTF-16BE');
|
|
}
|
|
else
|
|
{
|
|
return iconv('UTF-16BE','UTF-8',pack('H*', $matches[1]));
|
|
}
|
|
}
|
|
, $result);
|
|
}
|
|
if (self::$unEscapedSlashes) $result = str_replace('\/', '/', $result);
|
|
return $result;
|
|
}
|
|
|
|
public function decode($data)
|
|
{
|
|
$options = 0;
|
|
if (self::$bigIntAsString) {
|
|
if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) // PHP >= 5.4
|
|
|| PHP_MAJOR_VERSION > 5 // PHP >= 6.0
|
|
) {
|
|
$options |= JSON_BIGINT_AS_STRING;
|
|
} else {
|
|
$data = preg_replace(
|
|
'/:\s*(\-?\d+(\.\d+)?([e|E][\-|\+]\d+)?)/',
|
|
': "$1"', $data
|
|
);
|
|
}
|
|
}
|
|
$decoded = json_decode($data, $options);
|
|
if (function_exists('json_last_error')) {
|
|
switch (json_last_error()) {
|
|
case JSON_ERROR_NONE :
|
|
return Object::toArray($decoded);
|
|
break;
|
|
case JSON_ERROR_DEPTH :
|
|
$message = 'maximum stack depth exceeded';
|
|
break;
|
|
case JSON_ERROR_STATE_MISMATCH :
|
|
$message = 'underflow or the modes mismatch';
|
|
break;
|
|
case JSON_ERROR_CTRL_CHAR :
|
|
$message = 'unexpected control character found';
|
|
break;
|
|
case JSON_ERROR_SYNTAX :
|
|
$message = 'malformed JSON';
|
|
break;
|
|
case JSON_ERROR_UTF8 :
|
|
$message = 'malformed UTF-8 characters, possibly ' .
|
|
'incorrectly encoded';
|
|
break;
|
|
default :
|
|
$message = 'unknown error';
|
|
break;
|
|
}
|
|
throw new RestException (400, 'Error parsing JSON, ' . $message);
|
|
} elseif (strlen($data) && $decoded === null || $decoded === $data) {
|
|
throw new RestException (400, 'Error parsing JSON');
|
|
}
|
|
|
|
return Object::toArray($decoded);
|
|
}
|
|
|
|
/**
|
|
* Pretty print JSON string
|
|
*
|
|
* @param string $json
|
|
*
|
|
* @return string formatted json
|
|
*/
|
|
private function formatJson($json)
|
|
{
|
|
$tab = ' ';
|
|
$newJson = '';
|
|
$indentLevel = 0;
|
|
$inString = false;
|
|
$len = strlen($json);
|
|
for ($c = 0; $c < $len; $c++) {
|
|
$char = $json [$c];
|
|
switch ($char) {
|
|
case '{' :
|
|
case '[' :
|
|
if (!$inString) {
|
|
$newJson .= $char . "\n" .
|
|
str_repeat($tab, $indentLevel + 1);
|
|
$indentLevel++;
|
|
} else {
|
|
$newJson .= $char;
|
|
}
|
|
break;
|
|
case '}' :
|
|
case ']' :
|
|
if (!$inString) {
|
|
$indentLevel--;
|
|
$newJson .= "\n" .
|
|
str_repeat($tab, $indentLevel) . $char;
|
|
} else {
|
|
$newJson .= $char;
|
|
}
|
|
break;
|
|
case ',' :
|
|
if (!$inString) {
|
|
$newJson .= ",\n" .
|
|
str_repeat($tab, $indentLevel);
|
|
} else {
|
|
$newJson .= $char;
|
|
}
|
|
break;
|
|
case ':' :
|
|
if (!$inString) {
|
|
$newJson .= ': ';
|
|
} else {
|
|
$newJson .= $char;
|
|
}
|
|
break;
|
|
case '"' :
|
|
if ($c == 0) {
|
|
$inString = true;
|
|
} elseif ($c > 0 && $json [$c - 1] != '\\') {
|
|
$inString = !$inString;
|
|
}
|
|
default :
|
|
$newJson .= $char;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $newJson;
|
|
}
|
|
}
|
|
|