json.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Fanwe 方维直播系统
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2011 http://www.fanwe.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Author: 云淡风轻(1956838968@qq.com)
  8. // +----------------------------------------------------------------------
  9. /**
  10. * 将对象成员变量或者数组的特殊字符进行转义
  11. *
  12. * @access public
  13. * @param mix $obj 对象或者数组
  14. * @author Xuan Yan
  15. *
  16. * @return mix 对象或者数组
  17. */
  18. function addslashes_deep_obj($obj)
  19. {
  20. if (is_object($obj) == true)
  21. {
  22. foreach ($obj AS $key => $val)
  23. {
  24. $obj->$key = addslashes_deep($val);
  25. }
  26. }
  27. else
  28. {
  29. $obj = addslashes_deep($obj);
  30. }
  31. return $obj;
  32. }
  33. /**
  34. * 递归方式的对变量中的特殊字符进行转义
  35. *
  36. * @access public
  37. * @param mix $value
  38. *
  39. * @return mix
  40. */
  41. function addslashes_deep($value)
  42. {
  43. if (empty($value))
  44. {
  45. return $value;
  46. }
  47. else
  48. {
  49. return is_array($value) ? array_map('addslashes_deep', $value) : addslashes($value);
  50. }
  51. }
  52. class JSON
  53. {
  54. var $at = 0;
  55. var $ch = '';
  56. var $text = '';
  57. function encode($arg, $force = true)
  58. {
  59. static $_force;
  60. if (is_null($_force))
  61. {
  62. $_force = $force;
  63. }
  64. $returnValue = '';
  65. $c = '';
  66. $i = '';
  67. $l = '';
  68. $s = '';
  69. $v = '';
  70. $numeric = true;
  71. switch (gettype($arg))
  72. {
  73. case 'array':
  74. foreach ($arg AS $i => $v)
  75. {
  76. if (!is_numeric($i))
  77. {
  78. $numeric = false;
  79. break;
  80. }
  81. }
  82. if ($numeric)
  83. {
  84. foreach ($arg AS $i => $v)
  85. {
  86. if (strlen($s) > 0)
  87. {
  88. $s .= ',';
  89. }
  90. $s .= $this->encode($arg[$i]);
  91. }
  92. $returnValue = '[' . $s . ']';
  93. }
  94. else
  95. {
  96. foreach ($arg AS $i => $v)
  97. {
  98. if (strlen($s) > 0)
  99. {
  100. $s .= ',';
  101. }
  102. $s .= $this->encode($i) . ':' . $this->encode($arg[$i]);
  103. }
  104. $returnValue = '{' . $s . '}';
  105. }
  106. break;
  107. case 'object':
  108. foreach (get_object_vars($arg) AS $i => $v)
  109. {
  110. $v = $this->encode($v);
  111. if (strlen($s) > 0)
  112. {
  113. $s .= ',';
  114. }
  115. $s .= $this->encode($i) . ':' . $v;
  116. }
  117. $returnValue = '{' . $s . '}';
  118. break;
  119. case 'integer':
  120. case 'double':
  121. $returnValue = is_numeric($arg) ? (string) $arg : 'null';
  122. break;
  123. case 'string':
  124. $returnValue = '"' . strtr($arg, array(
  125. "\r" => '\\r', "\n" => '\\n', "\t" => '\\t', "\b" => '\\b',
  126. "\f" => '\\f', '\\' => '\\\\', '"' => '\"',
  127. "\x00" => '\u0000', "\x01" => '\u0001', "\x02" => '\u0002', "\x03" => '\u0003',
  128. "\x04" => '\u0004', "\x05" => '\u0005', "\x06" => '\u0006', "\x07" => '\u0007',
  129. "\x08" => '\b', "\x0b" => '\u000b', "\x0c" => '\f', "\x0e" => '\u000e',
  130. "\x0f" => '\u000f', "\x10" => '\u0010', "\x11" => '\u0011', "\x12" => '\u0012',
  131. "\x13" => '\u0013', "\x14" => '\u0014', "\x15" => '\u0015', "\x16" => '\u0016',
  132. "\x17" => '\u0017', "\x18" => '\u0018', "\x19" => '\u0019', "\x1a" => '\u001a',
  133. "\x1b" => '\u001b', "\x1c" => '\u001c', "\x1d" => '\u001d', "\x1e" => '\u001e',
  134. "\x1f" => '\u001f'
  135. )) . '"';
  136. break;
  137. case 'boolean':
  138. $returnValue = $arg?'true':'false';
  139. break;
  140. default:
  141. $returnValue = 'null';
  142. }
  143. return $returnValue;
  144. }
  145. function decode($text,$type=0) // 默认type=0返回obj,type=1返回array
  146. {
  147. if (empty($text))
  148. {
  149. return '';
  150. }
  151. elseif (!is_string($text))
  152. {
  153. return false;
  154. }
  155. $this->at = 0;
  156. $this->ch = '';
  157. $this->text = strtr(stripslashes($text), array(
  158. "\r" => '', "\n" => '', "\t" => '', "\b" => '',
  159. "\x00" => '', "\x01" => '', "\x02" => '', "\x03" => '',
  160. "\x04" => '', "\x05" => '', "\x06" => '', "\x07" => '',
  161. "\x08" => '', "\x0b" => '', "\x0c" => '', "\x0e" => '',
  162. "\x0f" => '', "\x10" => '', "\x11" => '', "\x12" => '',
  163. "\x13" => '', "\x14" => '', "\x15" => '', "\x16" => '',
  164. "\x17" => '', "\x18" => '', "\x19" => '', "\x1a" => '',
  165. "\x1b" => '', "\x1c" => '', "\x1d" => '', "\x1e" => '',
  166. "\x1f" => ''
  167. ));
  168. $this->next();
  169. $return = $this->val();
  170. $result = empty($type) ? $return : $this->object_to_array($return);
  171. return addslashes_deep_obj($result);
  172. }
  173. /**
  174. * triggers a PHP_ERROR
  175. *
  176. * @access private
  177. * @param string $m error message
  178. *
  179. * @return void
  180. */
  181. function error($m)
  182. {
  183. trigger_error($m . ' at offset ' . $this->at . ': ' . $this->text, E_USER_ERROR);
  184. }
  185. /**
  186. * returns the next character of a JSON string
  187. *
  188. * @access private
  189. *
  190. * @return string
  191. */
  192. function next()
  193. {
  194. $this->ch = !isset($this->text{$this->at}) ? '' : $this->text{$this->at};
  195. $this->at++;
  196. return $this->ch;
  197. }
  198. /**
  199. * handles strings
  200. *
  201. * @access private
  202. *
  203. * @return void
  204. */
  205. function str()
  206. {
  207. $i = '';
  208. $s = '';
  209. $t = '';
  210. $u = '';
  211. if ($this->ch == '"')
  212. {
  213. while ($this->next() !== null)
  214. {
  215. if ($this->ch == '"')
  216. {
  217. $this->next();
  218. return $s;
  219. }
  220. elseif ($this->ch == '\\')
  221. {
  222. switch ($this->next())
  223. {
  224. case 'b':
  225. $s .= '\b';
  226. break;
  227. case 'f':
  228. $s .= '\f';
  229. break;
  230. case 'n':
  231. $s .= '\n';
  232. break;
  233. case 'r':
  234. $s .= '\r';
  235. break;
  236. case 't':
  237. $s .= '\t';
  238. break;
  239. case 'u':
  240. $u = 0;
  241. for ($i = 0; $i < 4; $i++)
  242. {
  243. $t = (integer) sprintf('%01c', hexdec($this->next()));
  244. if (!is_numeric($t))
  245. {
  246. break 2;
  247. }
  248. $u = $u * 16 + $t;
  249. }
  250. $s .= chr($u);
  251. break;
  252. case '\'':
  253. $s .= '\'';
  254. break;
  255. default:
  256. $s .= $this->ch;
  257. }
  258. }
  259. else
  260. {
  261. $s .= $this->ch;
  262. }
  263. }
  264. }
  265. $this->error('Bad string');
  266. }
  267. /**
  268. * handless arrays
  269. *
  270. * @access private
  271. *
  272. * @return void
  273. */
  274. function arr()
  275. {
  276. $a = array();
  277. if ($this->ch == '[')
  278. {
  279. $this->next();
  280. if ($this->ch == ']')
  281. {
  282. $this->next();
  283. return $a;
  284. }
  285. while (isset($this->ch))
  286. {
  287. array_push($a, $this->val());
  288. if ($this->ch == ']')
  289. {
  290. $this->next();
  291. return $a;
  292. }
  293. elseif ($this->ch != ',')
  294. {
  295. break;
  296. }
  297. $this->next();
  298. }
  299. $this->error('Bad array');
  300. }
  301. }
  302. /**
  303. * handles objects
  304. *
  305. * @access public
  306. *
  307. * @return void
  308. */
  309. function obj()
  310. {
  311. $k = '';
  312. $o = new StdClass();
  313. if ($this->ch == '{')
  314. {
  315. $this->next();
  316. if ($this->ch == '}')
  317. {
  318. $this->next();
  319. return $o;
  320. }
  321. while ($this->ch)
  322. {
  323. $k = $this->str();
  324. if ($this->ch != ':')
  325. {
  326. break;
  327. }
  328. $this->next();
  329. $o->$k = $this->val();
  330. if ($this->ch == '}')
  331. {
  332. $this->next();
  333. return $o;
  334. }
  335. elseif ($this->ch != ',')
  336. {
  337. break;
  338. }
  339. $this->next();
  340. }
  341. }
  342. $this->error('Bad object');
  343. }
  344. /**
  345. * handles objects
  346. *
  347. * @access public
  348. *
  349. * @return void
  350. */
  351. function assoc()
  352. {
  353. $k = '';
  354. $a = array();
  355. if ($this->ch == '<')
  356. {
  357. $this->next();
  358. if ($this->ch == '>')
  359. {
  360. $this->next();
  361. return $a;
  362. }
  363. while ($this->ch)
  364. {
  365. $k = $this->str();
  366. if ($this->ch != ':')
  367. {
  368. break;
  369. }
  370. $this->next();
  371. $a[$k] = $this->val();
  372. if ($this->ch == '>')
  373. {
  374. $this->next();
  375. return $a;
  376. }
  377. elseif ($this->ch != ',')
  378. {
  379. break;
  380. }
  381. $this->next();
  382. }
  383. }
  384. $this->error('Bad associative array');
  385. }
  386. /**
  387. * handles numbers
  388. *
  389. * @access private
  390. *
  391. * @return void
  392. */
  393. function num()
  394. {
  395. $n = '';
  396. $v = '';
  397. if ($this->ch == '-')
  398. {
  399. $n = '-';
  400. $this->next();
  401. }
  402. while ($this->ch >= '0' && $this->ch <= '9')
  403. {
  404. $n .= $this->ch;
  405. $this->next();
  406. }
  407. if ($this->ch == '.')
  408. {
  409. $n .= '.';
  410. while ($this->next() && $this->ch >= '0' && $this->ch <= '9')
  411. {
  412. $n .= $this->ch;
  413. }
  414. }
  415. if ($this->ch == 'e' || $this->ch == 'E')
  416. {
  417. $n .= 'e';
  418. $this->next();
  419. if ($this->ch == '-' || $this->ch == '+')
  420. {
  421. $n .= $this->ch;
  422. $this->next();
  423. }
  424. while ($this->ch >= '0' && $this->ch <= '9')
  425. {
  426. $n .= $this->ch;
  427. $this->next();
  428. }
  429. }
  430. $v += $n;
  431. if (!is_numeric($v))
  432. {
  433. $this->error('Bad number');
  434. }
  435. else
  436. {
  437. return $v;
  438. }
  439. }
  440. /**
  441. * handles words
  442. *
  443. * @access private
  444. *
  445. * @return mixed
  446. */
  447. function word()
  448. {
  449. switch ($this->ch)
  450. {
  451. case 't':
  452. if ($this->next() == 'r' && $this->next() == 'u' && $this->next() == 'e')
  453. {
  454. $this->next();
  455. return true;
  456. }
  457. break;
  458. case 'f':
  459. if ($this->next() == 'a' && $this->next() == 'l' && $this->next() == 's' && $this->next() == 'e')
  460. {
  461. $this->next();
  462. return false;
  463. }
  464. break;
  465. case 'n':
  466. if ($this->next() == 'u' && $this->next() == 'l' && $this->next() == 'l')
  467. {
  468. $this->next();
  469. return null;
  470. }
  471. break;
  472. }
  473. $this->error('Syntax error');
  474. }
  475. /**
  476. * generic value handler
  477. *
  478. * @access private
  479. *
  480. * @return mixed
  481. */
  482. function val()
  483. {
  484. switch ($this->ch)
  485. {
  486. case '{':
  487. return $this->obj();
  488. case '[':
  489. return $this->arr();
  490. case '<':
  491. return $this->assoc();
  492. case '"':
  493. return $this->str();
  494. case '-':
  495. return $this->num();
  496. default:
  497. return ($this->ch >= '0' && $this->ch <= '9') ? $this->num() : $this->word();
  498. }
  499. }
  500. /**
  501. * Gets the properties of the given object recursion
  502. *
  503. * @access private
  504. *
  505. * @return array
  506. */
  507. function object_to_array($obj)
  508. {
  509. $_arr = is_object($obj) ? get_object_vars($obj) : $obj;
  510. foreach ($_arr as $key => $val)
  511. {
  512. $val = (is_array($val) || is_object($val)) ? $this->object_to_array($val) : $val;
  513. $arr[$key] = $val;
  514. }
  515. return $arr;
  516. }
  517. }
  518. ?>