JsonTest.php 30 KB

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