JsonTest.php 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  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-2015 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-2015 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. $iterator = new ArrayIterator(array(
  662. 'foo' => 'bar',
  663. 'baz' => 5
  664. ));
  665. $target = '{"__className":"ArrayIterator","foo":"bar","baz":5}';
  666. Zend_Json::$useBuiltinEncoderDecoder = true;
  667. $this->assertEquals($target, Zend_Json::encode($iterator));
  668. }
  669. /**
  670. * @group ZF-12347
  671. */
  672. public function testEncodeObjectImplementingIteratorAggregate()
  673. {
  674. $iterator = new ZF12347_IteratorAggregate();
  675. $target = '{"__className":"ZF12347_IteratorAggregate","foo":"bar","baz":5}';
  676. Zend_Json::$useBuiltinEncoderDecoder = true;
  677. $this->assertEquals($target, Zend_Json::encode($iterator));
  678. }
  679. /**
  680. * @group ZF-8663
  681. */
  682. public function testNativeJsonEncoderWillProperlyEncodeSolidusInStringValues()
  683. {
  684. $source = "</foo><foo>bar</foo>";
  685. $target = '"<\\/foo><foo>bar<\\/foo>"';
  686. // first test ext/json
  687. Zend_Json::$useBuiltinEncoderDecoder = false;
  688. $this->assertEquals($target, Zend_Json::encode($source));
  689. }
  690. /**
  691. * @group ZF-8663
  692. */
  693. public function testBuiltinJsonEncoderWillProperlyEncodeSolidusInStringValues()
  694. {
  695. $source = "</foo><foo>bar</foo>";
  696. $target = '"<\\/foo><foo>bar<\\/foo>"';
  697. // first test ext/json
  698. Zend_Json::$useBuiltinEncoderDecoder = true;
  699. $this->assertEquals($target, Zend_Json::encode($source));
  700. }
  701. /**
  702. * @group ZF-8918
  703. * @expectedException Zend_Json_Exception
  704. */
  705. public function testDecodingInvalidJsonShouldRaiseAnException()
  706. {
  707. Zend_Json::decode(' some string ');
  708. }
  709. /**
  710. * @group ZF-9416
  711. * Encoding an iterator using the internal encoder should handle undefined keys
  712. */
  713. public function testIteratorWithoutDefinedKey()
  714. {
  715. $inputValue = new ArrayIterator(array('foo'));
  716. $encoded = Zend_Json_Encoder::encode($inputValue);
  717. $expectedDecoding = '{"__className":"ArrayIterator","0":"foo"}';
  718. $this->assertEquals($encoded, $expectedDecoding);
  719. }
  720. /**
  721. * @group ZF-11356
  722. */
  723. public function testEncoderEscapesNamespacedClassNamesProperly()
  724. {
  725. if (version_compare(PHP_VERSION, '5.3.0') === -1) {
  726. $this->markTestSkipped('Namespaces not available in PHP < 5.3.0');
  727. }
  728. require_once dirname(__FILE__ ) . "/Json/_files/ZF11356-NamespacedClass.php";
  729. $className = '\Zend\JsonTest\ZF11356\NamespacedClass';
  730. $inputValue = new $className(array('foo'));
  731. $encoded = Zend_Json_Encoder::encode($inputValue);
  732. $this->assertEquals(
  733. '{"__className":"Zend\\\\JsonTest\\\\ZF11356\\\\NamespacedClass","0":"foo"}',
  734. $encoded
  735. );
  736. }
  737. /**
  738. * @group ZF-9577
  739. */
  740. public function testJsonPrettyPrintWorksWithTxtOutputFormat()
  741. {
  742. $o = new stdClass;
  743. $o->four = 4;
  744. $o->foo = array(1,2,3);
  745. $jsonstr = Zend_Json::encode($o);
  746. $targetTxtOutput = "{\n\t\"four\":4,\n\t\"foo\":[\n\t\t1,\n\t\t2,\n\t\t3\n\t]\n}";
  747. $this->assertEquals($targetTxtOutput, Zend_Json::prettyPrint($jsonstr));
  748. }
  749. /**
  750. * @group ZF-9577
  751. */
  752. public function testJsonPrettyPrintWorksWithHtmlOutputFormat()
  753. {
  754. $o = new stdClass;
  755. $o->four = 4;
  756. $o->foo = array(1,2,3);
  757. $jsonstr = Zend_Json::encode($o);
  758. $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 />}';
  759. $this->assertEquals($targetHtmlOutput, Zend_Json::prettyPrint($jsonstr, array('format' => 'html')));
  760. }
  761. /**
  762. * @group ZF-11167
  763. */
  764. public function testEncodeWillUseToArrayMethodWhenAvailable()
  765. {
  766. $o = new ZF11167_ToArrayClass();
  767. $objJson = Zend_Json::encode($o);
  768. $arrJson = Zend_Json::encode($o->toArray());
  769. $this->assertSame($arrJson, $objJson);
  770. }
  771. /**
  772. * @group ZF-11167
  773. */
  774. public function testEncodeWillUseToJsonWhenBothToJsonAndToArrayMethodsAreAvailable()
  775. {
  776. $o = new ZF11167_ToArrayToJsonClass();
  777. $objJson = Zend_Json::encode($o);
  778. $this->assertEquals('"bogus"', $objJson);
  779. $arrJson = Zend_Json::encode($o->toArray());
  780. $this->assertNotSame($objJson, $arrJson);
  781. }
  782. /**
  783. * @group ZF-9521
  784. */
  785. public function testWillEncodeArrayOfObjectsEachWithToJsonMethod()
  786. {
  787. $array = array('one'=>new ToJsonClass());
  788. $expected = '{"one":{"__className":"ToJsonClass","firstName":"John","lastName":"Doe","email":"john@doe.com"}}';
  789. Zend_Json::$useBuiltinEncoderDecoder = true;
  790. $json = Zend_Json::encode($array);
  791. $this->assertEquals($expected, $json);
  792. }
  793. /**
  794. * @group ZF-7586
  795. */
  796. public function testWillDecodeStructureWithEmptyKeyToObjectProperly()
  797. {
  798. Zend_Json::$useBuiltinEncoderDecoder = true;
  799. $json = '{"":"test"}';
  800. $object = Zend_Json::decode($json, Zend_Json::TYPE_OBJECT);
  801. $this->assertTrue(isset($object->_empty_));
  802. $this->assertEquals('test', $object->_empty_);
  803. }
  804. }
  805. /**
  806. * Zend_JsonTest_Item: test item for use with testZf461()
  807. */
  808. class Zend_JsonTest_Item
  809. {
  810. }
  811. /**
  812. * Zend_JsonTest_Object: test class for encoding classes
  813. */
  814. class Zend_JsonTest_Object
  815. {
  816. const FOO = 'bar';
  817. public $foo = 'bar';
  818. public $bar = 'baz';
  819. protected $_foo = 'fooled you';
  820. public function foo($bar, $baz)
  821. {
  822. }
  823. public function bar($baz)
  824. {
  825. }
  826. protected function baz()
  827. {
  828. }
  829. }
  830. class ToJsonClass
  831. {
  832. private $_firstName = 'John';
  833. private $_lastName = 'Doe';
  834. private $_email = 'john@doe.com';
  835. public function toJson()
  836. {
  837. $data = array(
  838. 'firstName' => $this->_firstName,
  839. 'lastName' => $this->_lastName,
  840. 'email' => $this->_email
  841. );
  842. return Zend_Json::encode($data);
  843. }
  844. }
  845. /**
  846. * Serializable class exposing a toArray() method
  847. * @see ZF-11167
  848. */
  849. class ZF11167_ToArrayClass
  850. {
  851. private $_firstName = 'John';
  852. private $_lastName = 'Doe';
  853. private $_email = 'john@doe.com';
  854. public function toArray()
  855. {
  856. $data = array(
  857. 'firstName' => $this->_firstName,
  858. 'lastName' => $this->_lastName,
  859. 'email' => $this->_email
  860. );
  861. return $data;
  862. }
  863. }
  864. /**
  865. * Serializable class exposing both toArray() and toJson() methods
  866. * @see ZF-11167
  867. */
  868. class ZF11167_ToArrayToJsonClass extends ZF11167_ToArrayClass
  869. {
  870. public function toJson()
  871. {
  872. return Zend_Json::encode('bogus');
  873. }
  874. }
  875. /**
  876. * ISSUE ZF-4946
  877. *
  878. */
  879. class Zend_Json_ToJsonWithExpr
  880. {
  881. private $_string = 'text';
  882. private $_int = 9;
  883. private $_expr = 'window.alert("Zend Json Expr")';
  884. public function toJson()
  885. {
  886. $data = array(
  887. 'expr' => new Zend_Json_Expr($this->_expr),
  888. 'int' => $this->_int,
  889. 'string' => $this->_string
  890. );
  891. return Zend_Json::encode($data, false, array('enableJsonExprFinder' => true));
  892. }
  893. }
  894. /**
  895. * @see ZF-12347
  896. */
  897. class ZF12347_IteratorAggregate implements IteratorAggregate
  898. {
  899. protected $array = array(
  900. 'foo' => 'bar',
  901. 'baz' => 5
  902. );
  903. public function getIterator() {
  904. return new ArrayIterator($this->array);
  905. }
  906. }