JsonTest.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Json
  17. * @subpackage UnitTests
  18. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * @see Zend_Json
  24. */
  25. require_once 'Zend/Json.php';
  26. /**
  27. * @see Zend_Json_Expr
  28. */
  29. require_once 'Zend/Json/Expr.php';
  30. /**
  31. * @see Zend_Json_Encoder
  32. */
  33. require_once 'Zend/Json/Encoder.php';
  34. /**
  35. * @see Zend_Json_Decoder
  36. */
  37. require_once 'Zend/Json/Decoder.php';
  38. /**
  39. * @category Zend
  40. * @package Zend_Json
  41. * @subpackage UnitTests
  42. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  43. * @license http://framework.zend.com/license/new-bsd New BSD License
  44. * @group Zend_Json
  45. */
  46. class Zend_JsonTest extends PHPUnit_Framework_TestCase
  47. {
  48. private $_originalUseBuiltinEncoderDecoderValue;
  49. public function setUp()
  50. {
  51. $this->_originalUseBuiltinEncoderDecoderValue = Zend_Json::$useBuiltinEncoderDecoder;
  52. }
  53. public function tearDown()
  54. {
  55. Zend_Json::$useBuiltinEncoderDecoder = $this->_originalUseBuiltinEncoderDecoderValue;
  56. }
  57. public function testJsonWithPhpJsonExtension()
  58. {
  59. if (!extension_loaded('json')) {
  60. $this->markTestSkipped('JSON extension is not loaded');
  61. }
  62. Zend_Json::$useBuiltinEncoderDecoder = false;
  63. $this->_testJson(array('string', 327, true, null));
  64. }
  65. public function testJsonWithBuiltins()
  66. {
  67. Zend_Json::$useBuiltinEncoderDecoder = true;
  68. $this->_testJson(array('string', 327, true, null));
  69. }
  70. /**
  71. * Test encoding and decoding in a single step
  72. * @param array $values array of values to test against encode/decode
  73. */
  74. protected function _testJson($values)
  75. {
  76. $encoded = Zend_Json::encode($values);
  77. $this->assertEquals($values, Zend_Json::decode($encoded));
  78. }
  79. /**
  80. * test null encoding/decoding
  81. */
  82. public function testNull()
  83. {
  84. $this->_testEncodeDecode(array(null));
  85. }
  86. /**
  87. * test boolean encoding/decoding
  88. */
  89. public function testBoolean()
  90. {
  91. $this->assertTrue(Zend_Json_Decoder::decode(Zend_Json_Encoder::encode(true)));
  92. $this->assertFalse(Zend_Json_Decoder::decode(Zend_Json_Encoder::encode(false)));
  93. }
  94. /**
  95. * test integer encoding/decoding
  96. */
  97. public function testInteger()
  98. {
  99. $this->_testEncodeDecode(array(-2));
  100. $this->_testEncodeDecode(array(-1));
  101. $zero = Zend_Json_Decoder::decode(Zend_Json_Encoder::encode(0));
  102. $this->assertEquals(0, $zero, 'Failed 0 integer test. Encoded: ' . serialize(Zend_Json_Encoder::encode(0)));
  103. }
  104. /**
  105. * @group ZF-10185
  106. */
  107. public function testJsonPrettyPrintWorksWithArrayNotationInStringLiteral()
  108. {
  109. $o = new stdClass();
  110. $o->test = 1;
  111. $o->faz = 'fubar';
  112. // The escaped double-quote in item 'stringwithjsonchars' ensures that
  113. // escaped double-quotes don't throw off prettyPrint's string literal detection
  114. $test = array(
  115. 'simple'=>'simple test string',
  116. 'stringwithjsonchars'=>'\"[1,2]',
  117. 'complex'=>array(
  118. 'foo'=>'bar',
  119. 'far'=>'boo',
  120. 'faz'=>array(
  121. 'obj'=>$o
  122. )
  123. )
  124. );
  125. $pretty = Zend_Json::prettyPrint(Zend_Json::encode($test), array("indent" => " "));
  126. $expected = <<<EOB
  127. {
  128. "simple":"simple test string",
  129. "stringwithjsonchars":"\\\\\\"[1,2]",
  130. "complex":{
  131. "foo":"bar",
  132. "far":"boo",
  133. "faz":{
  134. "obj":{
  135. "test":1,
  136. "faz":"fubar"
  137. }
  138. }
  139. }
  140. }
  141. EOB;
  142. $this->assertSame($expected, $pretty);
  143. }
  144. /**
  145. * test float encoding/decoding
  146. */
  147. public function testFloat()
  148. {
  149. $this->_testEncodeDecode(array(-2.1, 1.2));
  150. }
  151. /**
  152. * test string encoding/decoding
  153. */
  154. public function testString()
  155. {
  156. $this->_testEncodeDecode(array('string'));
  157. $this->assertEquals('', Zend_Json_Decoder::decode(Zend_Json_Encoder::encode('')), 'Empty string encoded: ' . serialize(Zend_Json_Encoder::encode('')));
  158. }
  159. /**
  160. * Test backslash escaping of string
  161. */
  162. public function testString2()
  163. {
  164. $string = 'INFO: Path \\\\test\\123\\abc';
  165. $expected = '"INFO: Path \\\\\\\\test\\\\123\\\\abc"';
  166. $encoded = Zend_Json_Encoder::encode($string);
  167. $this->assertEquals($expected, $encoded, 'Backslash encoding incorrect: expected: ' . serialize($expected) . '; received: ' . serialize($encoded) . "\n");
  168. $this->assertEquals($string, Zend_Json_Decoder::decode($encoded));
  169. }
  170. /**
  171. * Test newline escaping of string
  172. */
  173. public function testString3()
  174. {
  175. $expected = '"INFO: Path\nSome more"';
  176. $string = "INFO: Path\nSome more";
  177. $encoded = Zend_Json_Encoder::encode($string);
  178. $this->assertEquals($expected, $encoded, 'Newline encoding incorrect: expected ' . serialize($expected) . '; received: ' . serialize($encoded) . "\n");
  179. $this->assertEquals($string, Zend_Json_Decoder::decode($encoded));
  180. }
  181. /**
  182. * Test tab/non-tab escaping of string
  183. */
  184. public function testString4()
  185. {
  186. $expected = '"INFO: Path\\t\\\\tSome more"';
  187. $string = "INFO: Path\t\\tSome more";
  188. $encoded = Zend_Json_Encoder::encode($string);
  189. $this->assertEquals($expected, $encoded, 'Tab encoding incorrect: expected ' . serialize($expected) . '; received: ' . serialize($encoded) . "\n");
  190. $this->assertEquals($string, Zend_Json_Decoder::decode($encoded));
  191. }
  192. /**
  193. * Test double-quote escaping of string
  194. */
  195. public function testString5()
  196. {
  197. $expected = '"INFO: Path \"Some more\""';
  198. $string = 'INFO: Path "Some more"';
  199. $encoded = Zend_Json_Encoder::encode($string);
  200. $this->assertEquals($expected, $encoded, 'Quote encoding incorrect: expected ' . serialize($expected) . '; received: ' . serialize($encoded) . "\n");
  201. $this->assertEquals($string, Zend_Json_Decoder::decode($encoded));
  202. }
  203. /**
  204. * test indexed array encoding/decoding
  205. */
  206. public function testArray()
  207. {
  208. $array = array(1, 'one', 2, 'two');
  209. $encoded = Zend_Json_Encoder::encode($array);
  210. $this->assertSame($array, Zend_Json_Decoder::decode($encoded), 'Decoded array does not match: ' . serialize($encoded));
  211. }
  212. /**
  213. * test associative array encoding/decoding
  214. */
  215. public function testAssocArray()
  216. {
  217. $this->_testEncodeDecode(array(array('one' => 1, 'two' => 2)));
  218. }
  219. /**
  220. * test associative array encoding/decoding, with mixed key types
  221. */
  222. public function testAssocArray2()
  223. {
  224. $this->_testEncodeDecode(array(array('one' => 1, 2 => 2)));
  225. }
  226. /**
  227. * test associative array encoding/decoding, with integer keys not starting at 0
  228. */
  229. public function testAssocArray3()
  230. {
  231. $this->_testEncodeDecode(array(array(1 => 'one', 2 => 'two')));
  232. }
  233. /**
  234. * test object encoding/decoding (decoding to array)
  235. */
  236. public function testObject()
  237. {
  238. $value = new stdClass();
  239. $value->one = 1;
  240. $value->two = 2;
  241. $array = array('__className' => 'stdClass', 'one' => 1, 'two' => 2);
  242. $encoded = Zend_Json_Encoder::encode($value);
  243. $this->assertSame($array, Zend_Json_Decoder::decode($encoded));
  244. }
  245. /**
  246. * test object encoding/decoding (decoding to stdClass)
  247. */
  248. public function testObjectAsObject()
  249. {
  250. $value = new stdClass();
  251. $value->one = 1;
  252. $value->two = 2;
  253. $encoded = Zend_Json_Encoder::encode($value);
  254. $decoded = Zend_Json_Decoder::decode($encoded, Zend_Json::TYPE_OBJECT);
  255. $this->assertTrue(is_object($decoded), 'Not decoded as an object');
  256. $this->assertTrue($decoded instanceof StdClass, 'Not a StdClass object');
  257. $this->assertTrue(isset($decoded->one), 'Expected property not set');
  258. $this->assertEquals($value->one, $decoded->one, 'Unexpected value');
  259. }
  260. /**
  261. * Test that arrays of objects decode properly; see issue #144
  262. */
  263. public function testDecodeArrayOfObjects()
  264. {
  265. $value = '[{"id":1},{"foo":2}]';
  266. $expect = array(array('id' => 1), array('foo' => 2));
  267. $this->assertEquals($expect, Zend_Json_Decoder::decode($value));
  268. }
  269. /**
  270. * Test that objects of arrays decode properly; see issue #107
  271. */
  272. public function testDecodeObjectOfArrays()
  273. {
  274. $value = '{"codeDbVar" : {"age" : ["int", 5], "prenom" : ["varchar", 50]}, "234" : [22, "jb"], "346" : [64, "francois"], "21" : [12, "paul"]}';
  275. $expect = array(
  276. 'codeDbVar' => array(
  277. 'age' => array('int', 5),
  278. 'prenom' => array('varchar', 50),
  279. ),
  280. 234 => array(22, 'jb'),
  281. 346 => array(64, 'francois'),
  282. 21 => array(12, 'paul')
  283. );
  284. $this->assertEquals($expect, Zend_Json_Decoder::decode($value));
  285. }
  286. /**
  287. * Test encoding and decoding in a single step
  288. * @param array $values array of values to test against encode/decode
  289. */
  290. protected function _testEncodeDecode($values)
  291. {
  292. foreach ($values as $value) {
  293. $encoded = Zend_Json_Encoder::encode($value);
  294. $this->assertEquals($value, Zend_Json_Decoder::decode($encoded));
  295. }
  296. }
  297. /**
  298. * Test that version numbers such as 4.10 are encoded and decoded properly;
  299. * See ZF-377
  300. */
  301. public function testEncodeReleaseNumber()
  302. {
  303. $value = '4.10';
  304. $this->_testEncodeDecode(array($value));
  305. }
  306. /**
  307. * Tests that spaces/linebreaks prior to a closing right bracket don't throw
  308. * exceptions. See ZF-283.
  309. */
  310. public function testEarlyLineBreak()
  311. {
  312. $expected = array('data' => array(1, 2, 3, 4));
  313. $json = '{"data":[1,2,3,4' . "\n]}";
  314. $this->assertEquals($expected, Zend_Json_Decoder::decode($json));
  315. $json = '{"data":[1,2,3,4 ]}';
  316. $this->assertEquals($expected, Zend_Json_Decoder::decode($json));
  317. }
  318. /**
  319. * Tests for ZF-504
  320. *
  321. * Three confirmed issues reported:
  322. * - encoder improperly encoding empty arrays as structs
  323. * - decoder happily decoding clearly borked JSON
  324. * - decoder decoding octal values improperly (shouldn't decode them at all, as JSON does not support them)
  325. */
  326. public function testZf504()
  327. {
  328. $test = array();
  329. $this->assertSame('[]', Zend_Json_Encoder::encode($test));
  330. try {
  331. $json = '[a"],["a],[][]';
  332. $test = Zend_Json_Decoder::decode($json);
  333. $this->fail("Should not be able to decode '$json'");
  334. $json = '[a"],["a]';
  335. $test = Zend_Json_Decoder::decode($json);
  336. $this->fail("Should not be able to decode '$json'");
  337. } catch (Exception $e) {
  338. // success
  339. }
  340. try {
  341. $expected = 010;
  342. $test = Zend_Json_Decoder::decode('010');
  343. $this->fail('Octal values are not supported in JSON notation');
  344. } catch (Exception $e) {
  345. // sucess
  346. }
  347. }
  348. /**
  349. * Tests for ZF-461
  350. *
  351. * Check to see that cycling detection works properly
  352. */
  353. public function testZf461()
  354. {
  355. $item1 = new Zend_JsonTest_Item() ;
  356. $item2 = new Zend_JsonTest_Item() ;
  357. $everything = array() ;
  358. $everything['allItems'] = array($item1, $item2) ;
  359. $everything['currentItem'] = $item1 ;
  360. try {
  361. $encoded = Zend_Json_Encoder::encode($everything);
  362. } catch (Exception $e) {
  363. $this->fail('Object cycling checks should check for recursion, not duplicate usage of an item');
  364. }
  365. try {
  366. $encoded = Zend_Json_Encoder::encode($everything, true);
  367. $this->fail('Object cycling not allowed when cycleCheck parameter is true');
  368. } catch (Exception $e) {
  369. // success
  370. }
  371. }
  372. /**
  373. * Test for ZF-4053
  374. *
  375. * Check to see that cyclical exceptions are silenced when
  376. * $option['silenceCyclicalExceptions'] = true is used
  377. */
  378. public function testZf4053()
  379. {
  380. $item1 = new Zend_JsonTest_Item() ;
  381. $item2 = new Zend_JsonTest_Item() ;
  382. $everything = array() ;
  383. $everything['allItems'] = array($item1, $item2) ;
  384. $everything['currentItem'] = $item1 ;
  385. $options = array('silenceCyclicalExceptions'=>true);
  386. Zend_Json::$useBuiltinEncoderDecoder = true;
  387. $encoded = Zend_Json::encode($everything, true, $options);
  388. $json = '{"allItems":[{"__className":"Zend_JsonTest_Item"},{"__className":"Zend_JsonTest_Item"}],"currentItem":"* RECURSION (Zend_JsonTest_Item) *"}';
  389. $this->assertEquals($encoded,$json);
  390. }
  391. public function testEncodeObject()
  392. {
  393. $actual = new Zend_JsonTest_Object();
  394. $encoded = Zend_Json_Encoder::encode($actual);
  395. $decoded = Zend_Json_Decoder::decode($encoded, Zend_Json::TYPE_OBJECT);
  396. $this->assertTrue(isset($decoded->__className));
  397. $this->assertEquals('Zend_JsonTest_Object', $decoded->__className);
  398. $this->assertTrue(isset($decoded->foo));
  399. $this->assertEquals('bar', $decoded->foo);
  400. $this->assertTrue(isset($decoded->bar));
  401. $this->assertEquals('baz', $decoded->bar);
  402. $this->assertFalse(isset($decoded->_foo));
  403. }
  404. public function testEncodeClass()
  405. {
  406. $encoded = Zend_Json_Encoder::encodeClass('Zend_JsonTest_Object');
  407. $this->assertContains("Class.create('Zend_JsonTest_Object'", $encoded);
  408. $this->assertContains("ZAjaxEngine.invokeRemoteMethod(this, 'foo'", $encoded);
  409. $this->assertContains("ZAjaxEngine.invokeRemoteMethod(this, 'bar'", $encoded);
  410. $this->assertNotContains("ZAjaxEngine.invokeRemoteMethod(this, 'baz'", $encoded);
  411. $this->assertContains('variables:{foo:"bar",bar:"baz"}', $encoded);
  412. $this->assertContains('constants : {FOO: "bar"}', $encoded);
  413. }
  414. public function testEncodeClasses()
  415. {
  416. $encoded = Zend_Json_Encoder::encodeClasses(array('Zend_JsonTest_Object', 'Zend_JsonTest'));
  417. $this->assertContains("Class.create('Zend_JsonTest_Object'", $encoded);
  418. $this->assertContains("Class.create('Zend_JsonTest'", $encoded);
  419. }
  420. public function testToJsonSerialization()
  421. {
  422. $toJsonObject = new ToJsonClass();
  423. $result = Zend_Json::encode($toJsonObject);
  424. $this->assertEquals('{"firstName":"John","lastName":"Doe","email":"john@doe.com"}', $result);
  425. }
  426. /**
  427. * test encoding array with Zend_Json_Expr
  428. *
  429. * @group ZF-4946
  430. */
  431. public function testEncodingArrayWithExpr()
  432. {
  433. $expr = new Zend_Json_Expr('window.alert("Zend Json Expr")');
  434. $array = array('expr'=>$expr, 'int'=>9, 'string'=>'text');
  435. $result = Zend_Json::encode($array, false, array('enableJsonExprFinder' => true));
  436. $expected = '{"expr":window.alert("Zend Json Expr"),"int":9,"string":"text"}';
  437. $this->assertEquals($expected, $result);
  438. }
  439. /**
  440. * test encoding object with Zend_Json_Expr
  441. *
  442. * @group ZF-4946
  443. */
  444. public function testEncodingObjectWithExprAndInternalEncoder()
  445. {
  446. Zend_Json::$useBuiltinEncoderDecoder = true;
  447. $expr = new Zend_Json_Expr('window.alert("Zend Json Expr")');
  448. $obj = new stdClass();
  449. $obj->expr = $expr;
  450. $obj->int = 9;
  451. $obj->string = 'text';
  452. $result = Zend_Json::encode($obj, false, array('enableJsonExprFinder' => true));
  453. $expected = '{"__className":"stdClass","expr":window.alert("Zend Json Expr"),"int":9,"string":"text"}';
  454. $this->assertEquals($expected, $result);
  455. }
  456. /**
  457. * test encoding object with Zend_Json_Expr
  458. *
  459. * @group ZF-4946
  460. */
  461. public function testEncodingObjectWithExprAndExtJson()
  462. {
  463. if(!function_exists('json_encode')) {
  464. $this->markTestSkipped('Test only works with ext/json enabled!');
  465. }
  466. Zend_Json::$useBuiltinEncoderDecoder = false;
  467. $expr = new Zend_Json_Expr('window.alert("Zend Json Expr")');
  468. $obj = new stdClass();
  469. $obj->expr = $expr;
  470. $obj->int = 9;
  471. $obj->string = 'text';
  472. $result = Zend_Json::encode($obj, false, array('enableJsonExprFinder' => true));
  473. $expected = '{"expr":window.alert("Zend Json Expr"),"int":9,"string":"text"}';
  474. $this->assertEquals($expected, $result);
  475. }
  476. /**
  477. * test encoding object with ToJson and Zend_Json_Expr
  478. *
  479. * @group ZF-4946
  480. */
  481. public function testToJsonWithExpr()
  482. {
  483. Zend_Json::$useBuiltinEncoderDecoder = true;
  484. $obj = new Zend_Json_ToJsonWithExpr();
  485. $result = Zend_Json::encode($obj, false, array('enableJsonExprFinder' => true));
  486. $expected = '{"expr":window.alert("Zend Json Expr"),"int":9,"string":"text"}';
  487. $this->assertEquals($expected, $result);
  488. }
  489. /**
  490. * Regression tests for Zend_Json_Expr and mutliple keys with the same name.
  491. *
  492. * @group ZF-4946
  493. */
  494. public function testEncodingMultipleNestedSwitchingSameNameKeysWithDifferentJsonExprSettings()
  495. {
  496. $data = array(
  497. 0 => array(
  498. "alpha" => new Zend_Json_Expr("function(){}"),
  499. "beta" => "gamma",
  500. ),
  501. 1 => array(
  502. "alpha" => "gamma",
  503. "beta" => new Zend_Json_Expr("function(){}"),
  504. ),
  505. 2 => array(
  506. "alpha" => "gamma",
  507. "beta" => "gamma",
  508. )
  509. );
  510. $result = Zend_Json::encode($data, false, array('enableJsonExprFinder' => true));
  511. $this->assertEquals(
  512. '[{"alpha":function(){},"beta":"gamma"},{"alpha":"gamma","beta":function(){}},{"alpha":"gamma","beta":"gamma"}]',
  513. $result
  514. );
  515. }
  516. /**
  517. * Regression tests for Zend_Json_Expr and mutliple keys with the same name.
  518. *
  519. * @group ZF-4946
  520. */
  521. public function testEncodingMultipleNestedIteratedSameNameKeysWithDifferentJsonExprSettings()
  522. {
  523. $data = array(
  524. 0 => array(
  525. "alpha" => "alpha"
  526. ),
  527. 1 => array(
  528. "alpha" => "beta",
  529. ),
  530. 2 => array(
  531. "alpha" => new Zend_Json_Expr("gamma"),
  532. ),
  533. 3 => array(
  534. "alpha" => "delta",
  535. ),
  536. 4 => array(
  537. "alpha" => new Zend_Json_Expr("epsilon"),
  538. )
  539. );
  540. $result = Zend_Json::encode($data, false, array('enableJsonExprFinder' => true));
  541. $this->assertEquals('[{"alpha":"alpha"},{"alpha":"beta"},{"alpha":gamma},{"alpha":"delta"},{"alpha":epsilon}]', $result);
  542. }
  543. public function testDisabledJsonExprFinder()
  544. {
  545. Zend_Json::$useBuiltinEncoderDecoder = true;
  546. $data = array(
  547. 0 => array(
  548. "alpha" => new Zend_Json_Expr("function(){}"),
  549. "beta" => "gamma",
  550. ),
  551. );
  552. $result = Zend_Json::encode($data);
  553. $this->assertEquals(
  554. '[{"alpha":{"__className":"Zend_Json_Expr"},"beta":"gamma"}]',
  555. $result
  556. );
  557. }
  558. /**
  559. * @group ZF-4054
  560. */
  561. public function testEncodeWithUtf8IsTransformedToPackedSyntax()
  562. {
  563. $data = array("Отмена");
  564. $result = Zend_Json_Encoder::encode($data);
  565. $this->assertEquals('["\u041e\u0442\u043c\u0435\u043d\u0430"]', $result);
  566. }
  567. /**
  568. * @group ZF-4054
  569. *
  570. * This test contains assertions from the Solar Framework by Paul M. Jones
  571. * @link http://solarphp.com
  572. */
  573. public function testEncodeWithUtf8IsTransformedSolarRegression()
  574. {
  575. $expect = '"h\u00c3\u00a9ll\u00c3\u00b6 w\u00c3\u00b8r\u00c5\u201ad"';
  576. $this->assertEquals($expect, Zend_Json_Encoder::encode('héllö wørłd'));
  577. $this->assertEquals('héllö wørłd', Zend_Json_Decoder::decode($expect));
  578. $expect = '"\u0440\u0443\u0441\u0441\u0438\u0448"';
  579. $this->assertEquals($expect, Zend_Json_Encoder::encode("руссиш"));
  580. $this->assertEquals("руссиш", Zend_Json_Decoder::decode($expect));
  581. }
  582. /**
  583. * @group ZF-4054
  584. */
  585. public function testEncodeUnicodeStringSolarRegression()
  586. {
  587. $value = 'héllö wørłd';
  588. $expected = 'h\u00c3\u00a9ll\u00c3\u00b6 w\u00c3\u00b8r\u00c5\u201ad';
  589. $this->assertEquals($expected, Zend_Json_Encoder::encodeUnicodeString($value));
  590. $value = "\xC3\xA4";
  591. $expected = '\u00e4';
  592. $this->assertEquals($expected, Zend_Json_Encoder::encodeUnicodeString($value));
  593. $value = "\xE1\x82\xA0\xE1\x82\xA8";
  594. $expected = '\u10a0\u10a8';
  595. $this->assertEquals($expected, Zend_Json_Encoder::encodeUnicodeString($value));
  596. }
  597. /**
  598. * @group ZF-4054
  599. */
  600. public function testDecodeUnicodeStringSolarRegression()
  601. {
  602. $expected = 'héllö wørłd';
  603. $value = 'h\u00c3\u00a9ll\u00c3\u00b6 w\u00c3\u00b8r\u00c5\u201ad';
  604. $this->assertEquals($expected, Zend_Json_Decoder::decodeUnicodeString($value));
  605. $expected = "\xC3\xA4";
  606. $value = '\u00e4';
  607. $this->assertEquals($expected, Zend_Json_Decoder::decodeUnicodeString($value));
  608. $value = '\u10a0';
  609. $expected = "\xE1\x82\xA0";
  610. $this->assertEquals($expected, Zend_Json_Decoder::decodeUnicodeString($value));
  611. }
  612. /**
  613. * @group ZF-4054
  614. *
  615. * This test contains assertions from the Solar Framework by Paul M. Jones
  616. * @link http://solarphp.com
  617. */
  618. public function testEncodeWithUtf8IsTransformedSolarRegressionEqualsJsonExt()
  619. {
  620. if(function_exists('json_encode') == false) {
  621. $this->markTestSkipped('Test can only be run, when ext/json is installed.');
  622. }
  623. $this->assertEquals(
  624. json_encode('héllö wørłd'),
  625. Zend_Json_Encoder::encode('héllö wørłd')
  626. );
  627. $this->assertEquals(
  628. json_encode("руссиш"),
  629. Zend_Json_Encoder::encode("руссиш")
  630. );
  631. }
  632. /**
  633. * @group ZF-4946
  634. */
  635. public function testUtf8JsonExprFinder()
  636. {
  637. $data = array("Отмена" => new Zend_Json_Expr("foo"));
  638. Zend_Json::$useBuiltinEncoderDecoder = true;
  639. $result = Zend_Json::encode($data, false, array('enableJsonExprFinder' => true));
  640. $this->assertEquals('{"\u041e\u0442\u043c\u0435\u043d\u0430":foo}', $result);
  641. Zend_Json::$useBuiltinEncoderDecoder = false;
  642. $result = Zend_Json::encode($data, false, array('enableJsonExprFinder' => true));
  643. $this->assertEquals('{"\u041e\u0442\u043c\u0435\u043d\u0430":foo}', $result);
  644. }
  645. /**
  646. * @group ZF-4437
  647. */
  648. public function testKommaDecimalIsConvertedToCorrectJsonWithDot()
  649. {
  650. $localeInfo = localeconv();
  651. if($localeInfo['decimal_point'] != ",") {
  652. $this->markTestSkipped("This test only works for platforms where , is the decimal point separator.");
  653. }
  654. Zend_Json::$useBuiltinEncoderDecoder = true;
  655. $this->assertEquals("[1.20, 1.68]", Zend_Json_Encoder::encode(array(
  656. (float)"1,20", (float)"1,68"
  657. )));
  658. }
  659. public function testEncodeObjectImplementingIterator()
  660. {
  661. $this->markTestIncomplete('Test is not yet finished.');
  662. }
  663. /**
  664. * @group ZF-8663
  665. */
  666. public function testNativeJsonEncoderWillProperlyEncodeSolidusInStringValues()
  667. {
  668. $source = "</foo><foo>bar</foo>";
  669. $target = '"<\\/foo><foo>bar<\\/foo>"';
  670. // first test ext/json
  671. Zend_Json::$useBuiltinEncoderDecoder = false;
  672. $this->assertEquals($target, Zend_Json::encode($source));
  673. }
  674. /**
  675. * @group ZF-8663
  676. */
  677. public function testBuiltinJsonEncoderWillProperlyEncodeSolidusInStringValues()
  678. {
  679. $source = "</foo><foo>bar</foo>";
  680. $target = '"<\\/foo><foo>bar<\\/foo>"';
  681. // first test ext/json
  682. Zend_Json::$useBuiltinEncoderDecoder = true;
  683. $this->assertEquals($target, Zend_Json::encode($source));
  684. }
  685. /**
  686. * @group ZF-8918
  687. * @expectedException Zend_Json_Exception
  688. */
  689. public function testDecodingInvalidJsonShouldRaiseAnException()
  690. {
  691. Zend_Json::decode(' some string ');
  692. }
  693. /**
  694. * @group ZF-9416
  695. * Encoding an iterator using the internal encoder should handle undefined keys
  696. */
  697. public function testIteratorWithoutDefinedKey()
  698. {
  699. $inputValue = new ArrayIterator(array('foo'));
  700. $encoded = Zend_Json_Encoder::encode($inputValue);
  701. $expectedDecoding = '{"__className":"ArrayIterator","0":"foo"}';
  702. $this->assertEquals($encoded, $expectedDecoding);
  703. }
  704. /**
  705. * @group ZF-11356
  706. */
  707. public function testEncoderEscapesNamespacedClassNamesProperly()
  708. {
  709. if (version_compare(PHP_VERSION, '5.3.0') === -1) {
  710. $this->markTestSkipped('Namespaces not available in PHP < 5.3.0');
  711. }
  712. require_once dirname(__FILE__ ) . "/Json/_files/ZF11356-NamespacedClass.php";
  713. $className = '\Zend\JsonTest\ZF11356\NamespacedClass';
  714. $inputValue = new $className(array('foo'));
  715. $encoded = Zend_Json_Encoder::encode($inputValue);
  716. $this->assertEquals(
  717. '{"__className":"Zend\\\\JsonTest\\\\ZF11356\\\\NamespacedClass","0":"foo"}',
  718. $encoded
  719. );
  720. }
  721. /**
  722. * @group ZF-9577
  723. */
  724. public function testJsonPrettyPrintWorksWithTxtOutputFormat()
  725. {
  726. $o = new stdClass;
  727. $o->four = 4;
  728. $o->foo = array(1,2,3);
  729. $jsonstr = Zend_Json::encode($o);
  730. $targetTxtOutput = "{\n\t\"four\":4,\n\t\"foo\":[\n\t\t1,\n\t\t2,\n\t\t3\n\t]\n}";
  731. $this->assertEquals($targetTxtOutput, Zend_Json::prettyPrint($jsonstr));
  732. }
  733. /**
  734. * @group ZF-9577
  735. */
  736. public function testJsonPrettyPrintWorksWithHtmlOutputFormat()
  737. {
  738. $o = new stdClass;
  739. $o->four = 4;
  740. $o->foo = array(1,2,3);
  741. $jsonstr = Zend_Json::encode($o);
  742. $targetHtmlOutput = '{<br />&nbsp;&nbsp;&nbsp;&nbsp;"four":4,<br />&nbsp;&nbsp;&nbsp;&nbsp;"foo":[<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />&nbsp;&nbsp;&nbsp;&nbsp;]<br />}';
  743. $this->assertEquals($targetHtmlOutput, Zend_Json::prettyPrint($jsonstr, array('format' => 'html')));
  744. }
  745. /**
  746. * @group ZF-11167
  747. */
  748. public function testEncodeWillUseToArrayMethodWhenAvailable()
  749. {
  750. $o = new ZF11167_ToArrayClass();
  751. $objJson = Zend_Json::encode($o);
  752. $arrJson = Zend_Json::encode($o->toArray());
  753. $this->assertSame($arrJson, $objJson);
  754. }
  755. /**
  756. * @group ZF-11167
  757. */
  758. public function testEncodeWillUseToJsonWhenBothToJsonAndToArrayMethodsAreAvailable()
  759. {
  760. $o = new ZF11167_ToArrayToJsonClass();
  761. $objJson = Zend_Json::encode($o);
  762. $this->assertEquals('"bogus"', $objJson);
  763. $arrJson = Zend_Json::encode($o->toArray());
  764. $this->assertNotSame($objJson, $arrJson);
  765. }
  766. /**
  767. * @group ZF-9521
  768. */
  769. public function testWillEncodeArrayOfObjectsEachWithToJsonMethod()
  770. {
  771. $array = array('one'=>new ToJsonClass());
  772. $expected = '{"one":{"__className":"ToJsonClass","firstName":"John","lastName":"Doe","email":"john@doe.com"}}';
  773. Zend_Json::$useBuiltinEncoderDecoder = true;
  774. $json = Zend_Json::encode($array);
  775. $this->assertEquals($expected, $json);
  776. }
  777. /**
  778. * @group ZF-7586
  779. */
  780. public function testWillDecodeStructureWithEmptyKeyToObjectProperly()
  781. {
  782. Zend_Json::$useBuiltinEncoderDecoder = true;
  783. $json = '{"":"test"}';
  784. $object = Zend_Json::decode($json, Zend_Json::TYPE_OBJECT);
  785. $this->assertTrue(isset($object->_empty_));
  786. $this->assertEquals('test', $object->_empty_);
  787. }
  788. }
  789. /**
  790. * Zend_JsonTest_Item: test item for use with testZf461()
  791. */
  792. class Zend_JsonTest_Item
  793. {
  794. }
  795. /**
  796. * Zend_JsonTest_Object: test class for encoding classes
  797. */
  798. class Zend_JsonTest_Object
  799. {
  800. const FOO = 'bar';
  801. public $foo = 'bar';
  802. public $bar = 'baz';
  803. protected $_foo = 'fooled you';
  804. public function foo($bar, $baz)
  805. {
  806. }
  807. public function bar($baz)
  808. {
  809. }
  810. protected function baz()
  811. {
  812. }
  813. }
  814. class ToJsonClass
  815. {
  816. private $_firstName = 'John';
  817. private $_lastName = 'Doe';
  818. private $_email = 'john@doe.com';
  819. public function toJson()
  820. {
  821. $data = array(
  822. 'firstName' => $this->_firstName,
  823. 'lastName' => $this->_lastName,
  824. 'email' => $this->_email
  825. );
  826. return Zend_Json::encode($data);
  827. }
  828. }
  829. /**
  830. * Serializable class exposing a toArray() method
  831. * @see ZF-11167
  832. */
  833. class ZF11167_ToArrayClass
  834. {
  835. private $_firstName = 'John';
  836. private $_lastName = 'Doe';
  837. private $_email = 'john@doe.com';
  838. public function toArray()
  839. {
  840. $data = array(
  841. 'firstName' => $this->_firstName,
  842. 'lastName' => $this->_lastName,
  843. 'email' => $this->_email
  844. );
  845. return $data;
  846. }
  847. }
  848. /**
  849. * Serializable class exposing both toArray() and toJson() methods
  850. * @see ZF-11167
  851. */
  852. class ZF11167_ToArrayToJsonClass extends ZF11167_ToArrayClass
  853. {
  854. public function toJson()
  855. {
  856. return Zend_Json::encode('bogus');
  857. }
  858. }
  859. /**
  860. * ISSUE ZF-4946
  861. *
  862. */
  863. class Zend_Json_ToJsonWithExpr
  864. {
  865. private $_string = 'text';
  866. private $_int = 9;
  867. private $_expr = 'window.alert("Zend Json Expr")';
  868. public function toJson()
  869. {
  870. $data = array(
  871. 'expr' => new Zend_Json_Expr($this->_expr),
  872. 'int' => $this->_int,
  873. 'string' => $this->_string
  874. );
  875. return Zend_Json::encode($data, false, array('enableJsonExprFinder' => true));
  876. }
  877. }