PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/wind/utility/WindJson.php

https://github.com/cuijinquan/nextwind
PHP | 330 lines | 248 code | 10 blank | 72 comment | 55 complexity | be6bd3df53a5e20391f876d1f073e786 MD5 | raw file
  1. <?php
  2. Wind::import('WIND:utility.WindConvert');
  3. /**
  4. * json格式转换类
  5. *
  6. * 支持json转php类型,以及php类型转json.
  7. * @author Long.shi <long.shi@adlibaba-inc.com> 2011-10-19
  8. * @copyright ©2003-2103 phpwind.com
  9. * @license http://www.windframework.com
  10. * @version $Id: WindJson.php 3859 2012-12-18 09:25:51Z yishuo $
  11. * @package utility
  12. */
  13. class WindJson {
  14. const JSON_SLICE = 1;
  15. const JSON_IN_STR = 2;
  16. const JSON_IN_ARR = 4;
  17. const JSON_IN_OBJ = 8;
  18. const JSON_IN_CMT = 16;
  19. /**
  20. * 将数据用json加密
  21. *
  22. * @param mixed $value 要加密的值
  23. * @param string $charset
  24. * @return string
  25. */
  26. public static function encode($source, $charset = 'utf-8') {
  27. switch (gettype($source)) {
  28. case 'boolean':
  29. $source = $source ? 'true' : 'false';
  30. break;
  31. case 'NULL':
  32. $source = 'null';
  33. break;
  34. case 'integer':
  35. $source = (int) $source;
  36. break;
  37. case 'double':
  38. case 'float':
  39. $source = (float) $source;
  40. break;
  41. case 'string':
  42. $source = self::stringToJson($source, $charset);
  43. break;
  44. case 'array':
  45. $source = self::arrayToJson($source, $charset);
  46. break;
  47. case 'object':
  48. $source = self::objectToJson($source, $charset);
  49. break;
  50. default:
  51. break;
  52. }
  53. return $source;
  54. }
  55. /**
  56. * 将json格式数据解密
  57. *
  58. * @param string $str
  59. * @param boolean $toArray
  60. * @param string $charset
  61. * @return mixed
  62. */
  63. public static function decode($str, $toArray = true, $charset = 'utf8') {
  64. $str = self::_reduceString($str);
  65. $_str = strtolower($str);
  66. if ('true' == $_str) {
  67. return true;
  68. } elseif ('false' == $_str) {
  69. return false;
  70. } elseif ('null' == $_str) {
  71. return null;
  72. } elseif (is_numeric($str)) {
  73. return $str;
  74. } elseif (preg_match('/^("|\').*(\1)$/s', $_str, $matche) && $matche[1] == $matche[2]) {
  75. $str = self::jsonToString($str);
  76. } elseif (preg_match('/^\[.*\]$/s', $_str) || preg_match('/^\{.*\}$/s', $_str)) {
  77. $str = self::complexConvert($str, $toArray);
  78. }
  79. return WindConvert::convert($str, $charset, 'utf8');
  80. }
  81. /**
  82. * 将json格式转成php string类型
  83. *
  84. * @param string $string json字符串
  85. * @return Ambigous <string, unknown>
  86. */
  87. protected static function jsonToString($string) {
  88. $delim = substr($string, 0, 1);
  89. $chrs = substr($string, 1, -1);
  90. $decodeStr = '';
  91. for ($c = 0, $length = strlen($chrs); $c < $length; ++$c) {
  92. $compare = substr($chrs, $c, 2);
  93. $ordCode = ord($chrs{$c});
  94. if ('\b' == $compare) {
  95. $decodeStr .= chr(0x08);
  96. ++$c;
  97. } elseif ('\t' == $compare) {
  98. $decodeStr .= chr(0x09);
  99. ++$c;
  100. } elseif ('\n' == $compare) {
  101. $decodeStr .= chr(0x0A);
  102. ++$c;
  103. } elseif ('\f' == $compare) {
  104. $decodeStr .= chr(0x0C);
  105. ++$c;
  106. } elseif ('\r' == $compare) {
  107. $decodeStr .= chr(0x0D);
  108. ++$c;
  109. } elseif (in_array($compare, array('\\"', '\\\'', '\\\\', '\\/'))) {
  110. if (('"' == $delim && '\\\'' != $compare) || ("'" == $delim && '\\"' != $compare)) {
  111. $decodeStr .= $chrs{++$c};
  112. }
  113. } elseif (preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6))) {
  114. $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) . chr(hexdec(substr($chrs, ($c + 4), 2)));
  115. $decodeStr .= WindConvert::utf16beToUTF8($utf16); //self::utf16beToUTF8($utf16);
  116. $c += 5;
  117. } elseif (0x20 <= $ordCode && 0x7F >= $ordCode) {
  118. $decodeStr .= $chrs{$c};
  119. } elseif (0xC0 == ($ordCode & 0xE0)) {
  120. $decodeStr .= substr($chrs, $c, 2);
  121. ++$c;
  122. } elseif (0xE0 == ($ordCode & 0xF0)) {
  123. $decodeStr .= substr($chrs, $c, 3);
  124. $c += 2;
  125. } elseif (0xF0 == ($ordCode & 0xF8)) {
  126. $decodeStr .= substr($chrs, $c, 4);
  127. $c += 3;
  128. } elseif (0xF8 == ($ordCode & 0xFC)) {
  129. $decodeStr .= substr($chrs, $c, 5);
  130. $c += 4;
  131. } elseif (0xFC == ($ordCode & 0xFE)) {
  132. $decodeStr .= substr($chrs, $c, 6);
  133. $c += 5;
  134. }
  135. }
  136. return $decodeStr;
  137. }
  138. /**
  139. * 复杂的json格式转换,支持object array格式
  140. *
  141. * @param string $str
  142. * @param boolean $toArray
  143. * @return Ambigous <multitype:, stdClass>|multitype:|Ambigous <mixed, boolean, NULL, number, multitype:, stdClass, Ambigous, string, unknown>|boolean
  144. */
  145. protected static function complexConvert($str, $toArray = true) {
  146. if ('[' == $str{0}) {
  147. $stk = array(self::JSON_IN_ARR);
  148. $arr = array();
  149. } else {
  150. $obj = $toArray ? array() : new stdClass();
  151. $stk = array(self::JSON_IN_OBJ);
  152. }
  153. array_push($stk, array('what' => self::JSON_SLICE, 'where' => 0, 'delim' => false));
  154. $chrs = substr($str, 1, -1);
  155. $chrs = self::_reduceString($chrs);
  156. if ('' == $chrs) {
  157. return self::JSON_IN_ARR == reset($stk) ? $arr : $obj;
  158. }
  159. for ($c = 0, $length = strlen($chrs); $c <= $length; ++$c) {
  160. $top = end($stk);
  161. $substr_chrs_c_2 = substr($chrs, $c, 2);
  162. if (($c == $length) || (($chrs{$c} == ',') && ($top['what'] == self::JSON_SLICE))) {
  163. $slice = substr($chrs, $top['where'], ($c - $top['where']));
  164. array_push($stk, array('what' => self::JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
  165. if (reset($stk) == self::JSON_IN_ARR) {
  166. array_push($arr, self::decode($slice, $toArray));
  167. } elseif (reset($stk) == self::JSON_IN_OBJ) {
  168. if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
  169. $key = self::decode($parts[1], $toArray);
  170. $toArray ? $obj[$key] = self::decode($parts[2], $toArray) : $obj->$key = self::decode($parts[2],
  171. $toArray);
  172. } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
  173. $toArray ? $obj[$parts[1]] = self::decode($parts[2], $toArray) : $obj->$parts[1] = self::decode(
  174. $parts[2], $toArray);
  175. }
  176. }
  177. } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != self::JSON_IN_STR)) {
  178. array_push($stk, array('what' => self::JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
  179. } elseif (($chrs{$c} == $top['delim']) && ($top['what'] == self::JSON_IN_STR) && (($chrs{$c - 1} != "\\") || ($chrs{$c - 1} == "\\" && $chrs{$c - 2} == "\\"))) {
  180. array_pop($stk);
  181. } elseif (($chrs{$c} == '[') && in_array($top['what'],
  182. array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) {
  183. array_push($stk, array('what' => self::JSON_IN_ARR, 'where' => $c, 'delim' => false));
  184. } elseif (($chrs{$c} == ']') && ($top['what'] == self::JSON_IN_ARR)) {
  185. array_pop($stk);
  186. } elseif (($chrs{$c} == '{') && in_array($top['what'],
  187. array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) {
  188. array_push($stk, array('what' => self::JSON_IN_OBJ, 'where' => $c, 'delim' => false));
  189. } elseif (($chrs{$c} == '}') && ($top['what'] == self::JSON_IN_OBJ)) {
  190. array_pop($stk);
  191. } elseif (($substr_chrs_c_2 == '/*') && in_array($top['what'],
  192. array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) {
  193. array_push($stk, array('what' => self::JSON_IN_CMT, 'where' => ++$c, 'delim' => false));
  194. } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == self::JSON_IN_CMT)) {
  195. array_pop($stk);
  196. for ($i = $top['where']; $i <= ++$c; ++$i) {
  197. $chrs = substr_replace($chrs, ' ', $i, 1);
  198. }
  199. }
  200. }
  201. if (self::JSON_IN_ARR == reset($stk)) {
  202. return $arr;
  203. } elseif (self::JSON_IN_OBJ == reset($stk)) {
  204. return $obj;
  205. }
  206. return false;
  207. }
  208. /**
  209. * 将字符串转化成json格式对象
  210. *
  211. * @param string $string
  212. * @param string $charset
  213. * @return string
  214. */
  215. protected static function stringToJson($string, $charset = 'utf-8') {
  216. $string = WindConvert::convert($string, 'utf-8', $charset);
  217. $ascii = '';
  218. $strlen = strlen($string);
  219. for ($c = 0; $c < $strlen; ++$c) {
  220. $b = $string{$c};
  221. $ordVar = ord($string{$c});
  222. if (0x08 == $ordVar) {
  223. $ascii .= '\b';
  224. } elseif (0x09 == $ordVar) {
  225. $ascii .= '\t';
  226. } elseif (0x0A == $ordVar) {
  227. $ascii .= '\n';
  228. } elseif (0x0C == $ordVar) {
  229. $ascii .= '\f';
  230. } elseif (0x0D == $ordVar) {
  231. $ascii .= '\r';
  232. } elseif (in_array($ordVar, array(0x22, 0x2F, 0x5C))) {
  233. $ascii .= '\\' . $string{$c};
  234. } elseif (0x20 <= $ordVar && 0x7F >= $ordVar) {
  235. $ascii .= $string{$c}; //ASCII
  236. } elseif (0xC0 == ($ordVar & 0xE0)) {
  237. $char = pack('C*', $ordVar, ord($string{++$c}));
  238. $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char)));
  239. } elseif (0xE0 == ($ordVar & 0xF0)) {
  240. $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c}));
  241. $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char)));
  242. } elseif (0xF0 == ($ordVar & 0xF8)) {
  243. $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c}), ord($string{++$c}));
  244. $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char)));
  245. } elseif (0xF8 == ($ordVar & 0xFC)) {
  246. $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c}), ord($string{++$c}),
  247. ord($string{++$c}));
  248. $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char)));
  249. } elseif (0xFC == ($ordVar & 0xFE)) {
  250. $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c}), ord($string{++$c}),
  251. ord($string{++$c}), ord($string{++$c}));
  252. $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char)));
  253. }
  254. }
  255. return '"' . $ascii . '"';
  256. }
  257. /**
  258. * 将数组转化成json格式对象
  259. *
  260. * @param array $array
  261. * @param string $charset
  262. * @return string
  263. */
  264. protected static function arrayToJson(array $array, $charset = 'utf-8') {
  265. if (is_array($array) && count($array) && (array_keys($array) !== range(0, sizeof($array) - 1))) {
  266. array_walk($array, array('WindJson', '_nameValue'), $charset);
  267. return '{' . join(',', $array) . '}';
  268. }
  269. array_walk($array, array('WindJson', '_value'), $charset);
  270. return '[' . join(',', $array) . ']';
  271. }
  272. /**
  273. * 将对象转化成json格式对象
  274. *
  275. * @param string $object
  276. * @param string $charset
  277. * @return string
  278. */
  279. protected static function objectToJson($object, $charset = 'utf-8') {
  280. if ($object instanceof Traversable) {
  281. $vars = array();
  282. foreach ($object as $k => $v) {
  283. $vars[$k] = $v;
  284. }
  285. } else {
  286. $vars = get_object_vars($object);
  287. }
  288. array_walk($vars, array('WindJson', '_nameValue'), $charset);
  289. return '{' . join(',', $vars) . '}';
  290. }
  291. /**
  292. * @param string $str
  293. * @return string
  294. */
  295. private static function _reduceString($str) {
  296. return trim(preg_replace(array('#^\s*//(.+)$#m', '#^\s*/\*(.+)\*/#Us', '#/\*(.+)\*/\s*$#Us'), '', $str));
  297. }
  298. /**
  299. * callback函数,用于数组或对象加密
  300. *
  301. * @param mixed $name
  302. * @param mixed $value
  303. * @param string $charset
  304. */
  305. private static function _nameValue(&$value, $name, $charset) {
  306. $value = self::encode(strval($name), $charset) . ':' . self::encode($value, $charset);
  307. }
  308. /**
  309. * callback函数,用于数组加密(无key)
  310. *
  311. * @param mixed $value
  312. * @param mixed $name
  313. * @param string $charset
  314. */
  315. private static function _value(&$value, $name, $charset) {
  316. $value = self::encode($value, $charset);
  317. }
  318. }
  319. ?>