2007년 5월 29일 화요일

[php json] good!!!! via~ A comparison of php json libraries

A comparison of php json libraries

A completely fair and balanced comparison of php json libraries

Disclaimer: I'm biased

*** NOTE ***an updated version of this comparison has been published here on the 25th of April, 2007

The recent release of php 5.2.0, which includes by default an extension for converting php values from and to the JSON format, is a good occasion for comparing the different existing php libraries which aim to provide the same capabilities.

The JSON homepage lists quite a few php libraries, but only 4 are in fact available for download and look stable and maintained:

The first one is the only library written in C. Its evident advantage in terms of execution speed is (was) accompanied by portability problems that the other three, being written purely in php, do not have.

The second one was (to the best of my knowledge) the first implementation of JSON in PHP. Its inclusion in PEAR is a guarantee of stability and quality of code.

The third one is more recent, but it is backed up by the company behind the PHP engine, and is part of a framework of components that is very fashionable at the moment and will probably see widespread adoption in the future.

The fourth one was built to add support for the json-rpc protocol to an existing xmlrpc implementation, and later expanded to better handle plain json. The json parsing code was originally taken from the Pear lib and incrementally improved.

The comparison revolves around 4 sections: features matrix, code examples, execution speed and encoding/decoding test results.

All comparisons have been carried out on the most recent code available as of the beginning of November 2006 (read: CVS or unstable versions used where available)

Feature matrix

This list is quite subjective both on the choice of features looked for and in the evaluation of their implementation. I will gladly accept any correction.

FeaturePHP JsonPear JsonZend jsonXmlRpc json
Version 1.2.1 2006/03/311.31 2006/06/2820061105-1470CVS Id 1.25 2006/11/05
PHP version compatibility 4 (for windows the dll for php 4.3 and above is availabale on pecl4win), 54.0.6, 554.2, 5
PHP files used 0162
Encodes to 7-bit ASCII clean JSON strings, using unicode escape sequences YesYesNoYes
Supports encoding php strings from different charsets Assumes UTF-8Assumes UTF-8Does not convert string data: it is up to the user to take care about conversion to the desired charsetUTF-8, ISO-8859-1, ASCII
Supports decoding JSON data that has not an an array or object as top level element NoYesYesYes
Supports decoding JSON objects as either php arrays or objects YesYesYesYes
Supports distinguishing a failed decoding from decoding a single NULL value Yes (single NULL value cannot be decoded)NoYes (exception thrown)Yes
Supports decoding JSON to different charsets Only UTF-8

UTF-8, ISO-8859-1, ASCII
Supports features of Javascript outside the scope of JSON None: only data in accord with the Json spec is acceptedParses almost everything as valid (within an array)SomeTries to mimic the behaviour of common web browsers js engines;
keeps type information for float and integer php values (a float value of 1.0 will be encoded ad later decoded by the lib as float, even though in js only 'numbers' exists)
Extra features


Provides a compatibility layer that implement the same API as the PHP native json extension;
adds support for the json-rpc webservice dialect

Code samples

GoalPHP JsonPear JsonZend jsonXmlRpc json
Encode a php value to JSON string $out = json_encode($data); $value = new Services_JSON(); $out = $value->encode($data); $out = Zend_Json::encode($data); $value = php_jsonrpc_encode($data); $out = $value->serialize();
Decode a JSON string to PHP value (Json objects as php objects) $out = json_decode($data); $value = new Services_JSON(); $out = $value->decode($data); try { $out = Zend_Json::decode($data, Zend_Json::TYPE_OBJECT); } catch (Exception $e) { } $value = php_jsonrpc_decode_json($data); if ($value) $out = php_jsonrpc_decode($value, array('decode_php_objs'));
Decode a JSON string to PHP value (Json objects as php arrays) $out = json_decode($data, true); $value = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); $out = $value->decode($data); try { $out = Zend_Json::decode(); } catch (Exception $e) { } $value = php_jsonrpc_decode_json($data); if ($value) $out = php_jsonrpc_decode($value);

Speed comparison results

As with any benchmark results, take these with a grain of salt. No guarantee or claim of correctness is made.

A biggish php array was encoded then decoded 10 times in a row with each lib. Test results are in seconds, smaller is better.

The tests have been carried out on a Win XP machine, with PHP 5.1.6 and 5.2.0 running in CLI mode and a 'cleaned up' php.ini (and yes, I know most PHP applications are deployed on Linux, but that's what I had available at the moment. YMMV)

The XmlRpc lib appears twice because it can be used in two modes of operation: fully automated conversion or 'manual' conversion, where the user writes code to operate on the single jsonrpcval objects (see lib docs for more details).

PHP 5.1.6
TestPHP JsonPear JsonZend jsonXmlRpc json (a)XmlRpc json (m)
Data encoding 0.007980.238670.181980.681490.60186
Data decoding 0.013772.119080.699911.491281.41859
PHP 5.2.0
TestPHP JsonPear JsonZend jsonXmlRpc json (a)XmlRpc json (m)
Data encoding 0.008710.286580.464790.781070.73837
Data decoding 0.009472.236350.818781.700721.49629

An interesting result is PHP 5.2 seems to be slower on all libs, despite the claims made by the authors of it being much more optimized than its predecessors. Did I set it up wrong?

This is the data set used for testing, in PHP source format:

$data1 = array(1, 1.01, 'hello world', true, null, -1, 11.011, '~!@#$%^&*()_+|', false, null); $data2 = array('zero' => $data1, 'one' => $data1, 'two' => $data1, 'three' => $data1, 'four' => $data1, 'five' => $data1, 'six' => $data1, 'seven' => $data1, 'eight' => $data1, 'nine' => $data1); $data = array($data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2);

Encoding / decoding tests results

This last table is especially interesting, showing the different approach that the libraries have taken with regards to the JSON-vs-Javascript compatibility issue. In short: JSON is a subset of Javascript, and while every valid json string is valid Javascript, the reverse is not necessarily true. Every library I tested decodes correctly the json array defined as ["hello","world"], but not all of them accept as valid the string ['hello','world'], which is not valid Json but is valid javascript.

String decoding tests

ValueXmlRpc decodedJS dec.Native dec.Pear dec.Zend dec.
0string(0) "" NULL
'Invalid data (empty string?)'
NULL NULL NULL NULL
1string(1) "1" int(1) number(1) NULL int(1) int(1)
2string(4) "true" bool(true) bool(true) NULL bool(true) bool(true)
3string(4) "null" NULL NULL NULL NULL NULL
4string(7) ""hello"" string(5) "hello" string(5) "hello" NULL string(5) "hello" string(5) "hello"
5string(11) "not a value" NULL
'Invalid data'

NULL NULL NULL
'Illegal Token'
6string(2) "[]" array(0) { } array(0) { } array(0) { } array(0) { } array(0) { }
7string(3) "[1]" array(1) { [0]=> int(1) } array(1) { [0]=> number(1) } array(1) { [0]=> int(1) } array(1) { [0]=> int(1) } array(1) { [0]=> int(1) }
8string(5) "[1.1]" array(1) { [0]=> float(1.1) } array(1) { [0]=> number(1.1) } array(1) { [0]=> float(1.1) } array(1) { [0]=> float(1.1) } array(1) { [0]=> float(1.1) }
9string(7) "[-1E+4]" array(1) { [0]=> float(-10000) } array(1) { [0]=> number(-10000) } array(1) { [0]=> float(-10000) } array(1) { [0]=> float(-10000) } array(1) { [0]=> float(-10000) }
10string(10) "[100.0e-2]" array(1) { [0]=> float(1) } array(1) { [0]=> number(1) } array(1) { [0]=> float(1) } array(1) { [0]=> float(1) } array(1) { [0]=> float(1) }
11string(4) "[.5]" NULL
'Invalid data'
array(1) { [0]=> number(0.5) } NULL array(1) { [0]=> float(0.5) } array(1) { [0]=> float(0.5) }
12string(4) "[5.]" array(1) { [0]=> float(5) } array(1) { [0]=> number(5) } array(1) { [0]=> float(5) } array(1) { [0]=> int(5) } array(1) { [0]=> int(5) }
13string(3) "[.]" NULL
'Invalid data'

NULL array(1) { [0]=> NULL } NULL
'Illegal number format: .'
14string(6) "[5..5]" NULL
'Invalid data'

NULL array(1) { [0]=> NULL } NULL
'Missing "," in array encoding: [5..5]'
15string(5) "[10e]" NULL
'Invalid data'

NULL array(1) { [0]=> NULL } NULL
'Illegal Token'
16string(5) "[e10]" NULL
'Invalid data'

NULL array(1) { [0]=> NULL } NULL
'Illegal Token'
17string(7) "[010e2]" NULL
'Invalid data'

NULL array(1) { [0]=> float(1000) } array(1) { [0]=> float(1000) }
18string(7) "[010.2]" NULL
'Invalid data'

NULL array(1) { [0]=> float(10.2) } array(1) { [0]=> float(10.2) }
19string(5) "[010]" NULL
'Invalid data'
array(1) { [0]=> number(8) } NULL array(1) { [0]=> int(10) } array(1) { [0]=> int(10) }
20string(6) "[0xFF]" array(1) { [0]=> int(255) } array(1) { [0]=> number(255) } NULL array(1) { [0]=> int(0) } NULL
'Illegal Token'
21string(6) "[0xff]" array(1) { [0]=> int(255) } array(1) { [0]=> number(255) } NULL array(1) { [0]=> int(0) } NULL
'Illegal Token'
22string(6) "[true]" array(1) { [0]=> bool(true) } array(1) { [0]=> bool(true) } array(1) { [0]=> bool(true) } array(1) { [0]=> bool(true) } array(1) { [0]=> bool(true) }
23string(6) "[TRUE]" array(1) { [0]=> bool(true) }
NULL array(1) { [0]=> bool(true) } NULL
'Illegal Token'
24string(6) "[null]" array(1) { [0]=> NULL } array(1) { [0]=> undefined } array(1) { [0]=> NULL } array(1) { [0]=> NULL } array(1) { [0]=> NULL }
25string(6) "[NULL]" array(1) { [0]=> NULL }
NULL array(1) { [0]=> NULL } NULL
'Illegal Token'
26string(4) "[""]" array(1) { [0]=> string(0) "" } array(1) { [0]=> string(0) "" } array(1) { [0]=> string(0) "" } array(1) { [0]=> string(0) "" } array(1) { [0]=> string(0) "" }
27string(5) "["a"]" array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" }
28string(9) " [ "a" ] " array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" }
29string(4) "[1,]" array(2) { [0]=> int(1) [1]=> NULL } array(1) { [0]=> number(1) } NULL array(2) { [0]=> int(1) [1]=> NULL } array(1) { [0]=> int(1) }
30string(3) "[,]" array(2) { [0]=> NULL [1]=> NULL } array(1) { [0]=> undefined } NULL array(2) { [0]=> NULL [1]=> NULL } array(1) { [0]=> NULL }
31string(4) "[,1]" array(2) { [0]=> NULL [1]=> int(1) } array(2) { [0]=> undefined [1]=> number(1) } NULL array(2) { [0]=> NULL [1]=> int(1) } array(2) { [0]=> NULL [1]=> int(1) }
32string(6) "[1,,1]" array(3) { [0]=> int(1) [1]=> NULL [2]=> int(1) } array(3) { [0]=> number(1) [1]=> undefined [2]=> number(1) } NULL array(3) { [0]=> int(1) [1]=> NULL [2]=> int(1) } array(3) { [0]=> int(1) [1]=> NULL [2]=> int(1) }
33string(19) "// comment here [1]" NULL
'Invalid data'

NULL array(1) { [0]=> int(1) } NULL
'Illegal Token'
34string(19) "[// comment here 1]" NULL
'Invalid data'

NULL array(1) { [0]=> int(1) } NULL
'Illegal Token'
35string(19) "[1// comment here ]" NULL
'Invalid data'

NULL array(1) { [0]=> NULL } NULL
'Illegal Token'
36string(19) "[1]// comment here " NULL
'Invalid data (array missing closing bracket?)'

NULL NULL NULL
'Illegal Token'
37string(19) "/*comment here*/[1]" array(1) { [0]=> int(1) } array(1) { [0]=> number(1) } NULL array(1) { [0]=> int(1) } NULL
'Illegal Token'
38string(19) "[/*comment here*/1]" array(1) { [0]=> int(1) } array(1) { [0]=> number(1) } NULL array(1) { [0]=> int(1) } NULL
'Illegal Token'
39string(19) "[1/*comment here*/]" array(1) { [0]=> int(1) } array(1) { [0]=> number(1) } NULL array(1) { [0]=> int(1) } NULL
'Illegal Token'
40string(19) "[1]/*comment here*/" array(1) { [0]=> int(1) } array(1) { [0]=> number(1) } NULL array(1) { [0]=> int(1) } NULL
'Illegal Token'
41string(7) "/**/[1]" array(1) { [0]=> int(1) } array(1) { [0]=> number(1) } NULL NULL NULL
'Illegal Token'
42string(6) "// [1]" NULL
'Invalid data'

NULL NULL NULL
'Illegal Token'
43string(20) "[1 // comment here ]" NULL
'Invalid data'

NULL array(1) { [0]=> int(1) } NULL
'Illegal Token'
44string(20) "[ // comment here 1]" NULL
'Invalid data'

NULL array(1) { [0]=> int(1) } NULL
'Illegal Token'
45string(18) "[1]// comment here" NULL
'Invalid data (array missing closing bracket?)'
array(1) { [0]=> number(1) } NULL NULL NULL
'Illegal Token'
46string(19) "[1] // comment here" NULL
'Invalid data (array missing closing bracket?)'

NULL array(1) { [0]=> int(1) } NULL
'Illegal Token'
47string(28) "["a // this is a comment b"]" NULL
'Invalid data (line terminator char inside string?)'

NULL array(1) { [0]=> string(2) "ab" } array(1) { [0]=> string(24) "a // this is a comment b" }
48string(32) "["a // this is not a comment b"]" array(1) { [0]=> string(28) "a // this is not a comment b" } array(1) { [0]=> string(28) "a // this is not a comment b" } array(1) { [0]=> string(28) "a // this is not a comment b" } array(1) { [0]=> string(28) "a // this is not a comment b" } array(1) { [0]=> string(28) "a // this is not a comment b" }
49string(5) "['a']" array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } NULL array(1) { [0]=> string(1) "a" } NULL
'Illegal Token'
50string(4) "["a]" NULL
'Invalid data (string missing closing quote?)'

NULL array(1) { [0]=> NULL } array(1) { [0]=> string(2) "a]" }
51string(4) "[a"]" NULL
'Invalid data (string missing closing quote?)'

NULL array(1) { [0]=> NULL } NULL
'Illegal Token'
52string(5) "['a"]" NULL
'Invalid data (string missing closing quote?)'

NULL array(1) { [0]=> NULL } NULL
'Illegal Token'
53string(5) "["a']" NULL
'Invalid data (string missing closing quote?)'

NULL array(1) { [0]=> NULL } array(1) { [0]=> string(3) "a']" }
54string(3) "[']" NULL
'Invalid data (string missing closing quote?)'

NULL array(1) { [0]=> NULL } NULL
'Illegal Token'
55string(4) "['']" array(1) { [0]=> string(0) "" } array(1) { [0]=> string(0) "" } NULL array(1) { [0]=> string(0) "" } NULL
'Illegal Token'
56string(5) "[''']" NULL
'Invalid data (string missing closing quote?)'

NULL array(1) { [0]=> NULL } NULL
'Illegal Token'
57string(3) "["]" NULL
'Invalid data (string missing closing quote?)'

NULL array(1) { [0]=> NULL } array(1) { [0]=> string(1) "]" }
58string(5) "["""]" NULL
'Invalid data (string missing closing quote?)'

NULL array(1) { [0]=> NULL } NULL
'Missing "," in array encoding: ["""]'
59string(5) "["'"]" array(1) { [0]=> string(1) "'" } array(1) { [0]=> string(1) "'" } array(1) { [0]=> string(1) "'" } array(1) { [0]=> string(1) "'" } array(1) { [0]=> string(1) "'" }
60string(5) "['"']" array(1) { [0]=> string(1) """ } array(1) { [0]=> string(1) """ } NULL array(1) { [0]=> string(1) """ } NULL
'Illegal Token'
61string(6) "["\'"]" array(1) { [0]=> string(1) "'" } array(1) { [0]=> string(1) "'" } NULL array(1) { [0]=> string(1) "'" } NULL
'Illegal escape sequence ''''
62string(7) "["\\'"]" array(1) { [0]=> string(2) "\'" } array(1) { [0]=> string(2) "\'" } array(1) { [0]=> string(2) "\'" } array(1) { [0]=> string(2) "\'" } array(1) { [0]=> string(2) "\'" }
63string(6) "["\""]" array(1) { [0]=> string(1) """ } array(1) { [0]=> string(1) """ } array(1) { [0]=> string(1) """ } array(1) { [0]=> string(1) """ } array(1) { [0]=> string(1) """ }
64string(5) "["\"]" NULL
'Invalid data (string missing closing quote?)'

NULL array(1) { [0]=> string(1) "\" } array(1) { [0]=> string(2) ""]" }
65string(6) "["\\"]" array(1) { [0]=> string(1) "\" } array(1) { [0]=> string(1) "\" } array(1) { [0]=> string(1) "\" } array(1) { [0]=> string(1) "\" } array(1) { [0]=> string(1) "\" }
66string(7) "["\\\"]" NULL
'Invalid data (string missing closing quote?)'

NULL array(1) { [0]=> string(2) "\\" } array(1) { [0]=> string(3) "\"]" }
67string(6) " ["a"]" array(1) { [0]=> string(1) "a" }
array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" }
68string(6) "[ "a"]" array(1) { [0]=> string(1) "a" }
array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" }
69string(6) "["a "]" NULL
'Invalid data (line terminator char inside string?)'

NULL array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(2) "a " }
70string(6) "["a" ]" array(1) { [0]=> string(1) "a" }
array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" }
71string(6) "["a"] " array(1) { [0]=> string(1) "a" }
array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" } array(1) { [0]=> string(1) "a" }
72string(16) "["\u0041\u00DC"]" array(1) { [0]=> string(2) "AÜ" } array(1) { [0]=> string(2) "AÜ" } array(1) { [0]=> string(3) "AÃœ" } array(1) { [0]=> string(3) "AÃœ" } NULL
'Illegal escape sequence 'u''
73string(16) "["\b\t\f\v\r\n"]" array(1) { [0]=> string(6) " " } array(1) { [0]=> string(6) " " } NULL array(1) { [0]=> string(7) " \v " } NULL
'Illegal escape sequence 'v''
74string(14) "["\b\t\f\r\n"]" array(1) { [0]=> string(5) " " } array(1) { [0]=> string(5) " " } array(1) { [0]=> string(5) " " } array(1) { [0]=> string(5) " " } array(1) { [0]=> string(5) " " }
75string(12) "["\x41\xDC"]" array(1) { [0]=> string(2) "AÜ" } array(1) { [0]=> string(2) "AÜ" } NULL array(1) { [0]=> string(8) "\x41\xDC" } NULL
'Illegal escape sequence 'x''
76string(7) "[ ] [ ]" NULL
'Invalid data (unmatched array closing bracket?)'

NULL array(1) { [0]=> NULL } array(0) { }
77string(9) "["a" "b"]" NULL
'Invalid data (unescaped quote char inside string?)'

NULL array(1) { [0]=> string(5) "a" "b" } NULL
'Missing "," in array encoding: ["a" "b"]'
78string(5) "[1 2]" NULL
'Invalid data'

NULL array(1) { [0]=> NULL } NULL
'Missing "," in array encoding: [1 2]'
79string(4) "[{}]" array(1) { [0]=> array(0) { } } array(1) { [0]=> object(stdClass) (0) { } } array(1) { [0]=> object(stdClass)#5 (0) { } } array(1) { [0]=> array(0) { } } array(1) { [0]=> array(0) { } }
80string(7) "[ { } ]" array(1) { [0]=> array(0) { } } array(1) { [0]=> object(stdClass) (0) { } } array(1) { [0]=> object(stdClass)#7 (0) { } } array(1) { [0]=> array(0) { } } array(1) { [0]=> array(0) { } }
81string(5) "[{1}]" NULL
'Invalid data (missing object member name?)'

NULL array(1) { [0]=> array(0) { } } NULL
'Missing key in object encoding: [{1}]'
82string(7) "[{1:1}]" array(1) { [0]=> array(1) { [1]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [1]=> number(1) } } NULL array(1) { [0]=> array(1) { [1]=> int(1) } } NULL
'Missing key in object encoding: [{1:1}]'
83string(6) "[{:1}]" NULL
'Invalid data (missing object member name?)'

NULL array(1) { [0]=> array(0) { } } NULL
'Missing key in object encoding: [{:1}]'
84string(8) "[{"1":}]" NULL
'Invalid data (empty string?)'

NULL array(1) { [0]=> array(0) { } } array(1) { [0]=> array(1) { [1]=> NULL } }
85string(9) "[{"1":1}]" array(1) { [0]=> array(1) { [1]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [1]=> number(1) } } array(1) { [0]=> object(stdClass)#7 (1) { ["1"]=> int(1) } } array(1) { [0]=> array(1) { [1]=> int(1) } } array(1) { [0]=> array(1) { [1]=> int(1) } }
86string(8) "[{"":1}]" array(1) { [0]=> array(1) { [""]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { []=> number(1) } } array(1) { [0]=> object(stdClass)#5 (1) { ["_empty_"]=> int(1) } } array(1) { [0]=> array(0) { } } array(1) { [0]=> array(1) { [""]=> int(1) } }
87string(8) "[{"a":}]" NULL
'Invalid data (empty string?)'

NULL array(1) { [0]=> array(0) { } } array(1) { [0]=> array(1) { ["a"]=> NULL } }
88string(9) "[{"a":1}]" array(1) { [0]=> array(1) { ["a"]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [a]=> number(1) } } array(1) { [0]=> object(stdClass)#5 (1) { ["a"]=> int(1) } } array(1) { [0]=> array(1) { ["a"]=> int(1) } } array(1) { [0]=> array(1) { ["a"]=> int(1) } }
89string(12) "[{"true":1}]" array(1) { [0]=> array(1) { ["true"]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [true]=> number(1) } } array(1) { [0]=> object(stdClass)#7 (1) { ["true"]=> int(1) } } array(1) { [0]=> array(1) { ["true"]=> int(1) } } array(1) { [0]=> array(1) { ["true"]=> int(1) } }
90string(10) "[{true:1}]" array(1) { [0]=> array(1) { ["true"]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [true]=> number(1) } } NULL array(1) { [0]=> array(1) { ["true"]=> int(1) } } NULL
'Missing key in object encoding: [{true:1}]'
91string(10) "[{null:1}]" array(1) { [0]=> array(1) { ["null"]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [null]=> number(1) } } NULL array(1) { [0]=> array(1) { ["null"]=> int(1) } } NULL
'Missing key in object encoding: [{null:1}]'
92string(11) "[{a "a":1}]" array(1) { [0]=> array(1) { ["a "a""]=> int(1) } }
NULL array(1) { [0]=> array(0) { } } NULL
'Illegal Token'
93string(12) "[{"a":1"a"}]" NULL
'Invalid data'

NULL array(1) { [0]=> array(1) { ["a"]=> NULL } } NULL
'Missing "," in object encoding: [{"a":1"a"}]'
94string(11) "[{a b:"a"}]" array(1) { [0]=> array(1) { ["a b"]=> string(1) "a" } }
NULL array(1) { [0]=> array(0) { } } NULL
'Illegal Token'
95string(11) "[{a b:a b}]" NULL
'Invalid data'

NULL array(1) { [0]=> array(0) { } } NULL
'Illegal Token'
96string(11) "[{a 1:a 1}]" NULL
'Invalid data'

NULL array(1) { [0]=> array(0) { } } NULL
'Illegal Token'
97string(9) "[{a:b:c}]" NULL
'Invalid data'

NULL array(1) { [0]=> array(1) { ["a"]=> NULL } } NULL
'Illegal Token'
98string(25) "[/*comment here*/{"1":1}]" array(1) { [0]=> array(1) { [1]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [1]=> number(1) } } NULL array(1) { [0]=> array(1) { [1]=> int(1) } } NULL
'Illegal Token'
99string(25) "[{/*comment here*/"1":1}]" array(1) { [0]=> array(1) { [1]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [1]=> number(1) } } NULL array(1) { [0]=> array(1) { [1]=> int(1) } } NULL
'Illegal Token'
100string(25) "[{"1"/*comment here*/:1}]" array(1) { [0]=> array(1) { [1]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [1]=> number(1) } } NULL array(1) { [0]=> array(1) { [1]=> int(1) } } NULL
'Illegal Token'
101string(25) "[{"1":/*comment here*/1}]" array(1) { [0]=> array(1) { [1]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [1]=> number(1) } } NULL array(1) { [0]=> array(1) { [1]=> int(1) } } NULL
'Illegal Token'
102string(25) "[{"1":1/*comment here*/}]" array(1) { [0]=> array(1) { [1]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [1]=> number(1) } } NULL array(1) { [0]=> array(1) { [1]=> int(1) } } NULL
'Illegal Token'
103string(25) "[{"1":1}/*comment here*/]" array(1) { [0]=> array(1) { [1]=> int(1) } } array(1) { [0]=> object(stdClass) (1) { [1]=> number(1) } } NULL array(1) { [0]=> array(1) { [1]=> int(1) } } NULL
'Illegal Token'

Values encoding tests

ValueXmlRpc encodedNative enc.Pear enc.Zend enc.
0bool(true) string(4) "true" string(4) "true" string(4) "true" string(4) "true"
1bool(false) string(5) "false" string(5) "false" string(5) "false" string(5) "false"
2int(0) string(1) "0" string(1) "0" int(0) string(1) "0"
3int(1) string(1) "1" string(1) "1" int(1) string(1) "1"
4float(1) string(3) "1.0" string(1) "1" float(1) string(1) "1"
5float(1.1) string(3) "1.1" string(3) "1.1" float(1.1) string(3) "1.1"
6string(0) "" string(2) """" string(2) """" string(2) """" string(2) """"
7NULL string(4) "null" string(4) "null" string(4) "null" string(4) "null"
8string(1) "1" string(3) ""1"" string(3) ""1"" string(3) ""1"" string(3) ""1""
9string(17) "20060101T12:00:00" string(19) ""20060101T12:00:00"" string(19) ""20060101T12:00:00"" string(19) ""20060101T12:00:00"" string(19) ""20060101T12:00:00""
10string(15) "Günter, Elène" string(25) ""G\u00fcnter, El\u00e8ne"" string(25) ""G\u00fcnter, El\u00e8ne"" string(25) ""G\u00fcnter, El\u00e8ne"" string(17) ""Günter, Elène""
11string(13) "Günter, Elène" string(19) ""Gnter, El\u8ba5ne"" string(3) ""G"" string(38) ""G\u006e007400650072002c El\u006e0065"" string(15) ""Günter, Elène""
12resource(9) of type (stream) string(4) "null"
Warning: [json] (json_encode_r) type is unsupported, encoded as null. in C:\htdocs\xmlrpc_cvs\extras\jsonrpc\testsuite.php on line 381
string(4) "null"
NULL string(4) "null"
13string(8) "aGVsbG8=" string(10) ""aGVsbG8="" string(10) ""aGVsbG8="" string(10) ""aGVsbG8="" string(10) ""aGVsbG8=""
14object(jsonrpcmsg)#2 (6) { ["id"]=> NULL ["content_type"]=> string(10) "text/plain" ["payload"]=> NULL ["methodname"]=> string(5) "dummy" ["params"]=> array(0) { } ["debug"]=> int(0) } string(98) "{"id":null,"content_type":"text\/plain","payload":null,"methodname":"dummy","params":[],"debug":0}" string(98) "{"id":null,"content_type":"text\/plain","payload":null,"methodname":"dummy","params":[],"debug":0}" string(98) "{"id":null,"content_type":"text\/plain","payload":null,"methodname":"dummy","params":[],"debug":0}" string(99) "{"__className":"jsonrpcmsg","content_type":"text/plain","methodname":"dummy","params":{},"debug":0}"
15object(xmlrpcval)#3 (3) { ["me"]=> array(0) { } ["mytype"]=> int(0) ["_php_class"]=> NULL } string(38) "{"me":[],"mytype":0,"_php_class":null}" string(38) "{"me":[],"mytype":0,"_php_class":null}" string(38) "{"me":[],"mytype":0,"_php_class":null}" string(46) "{"__className":"xmlrpcval","me":{},"mytype":0}"
16array(0) { } string(2) "[]" string(2) "[]" string(2) "[]" string(2) "{}"
17array(1) { [0]=> string(15) "Günter, Elène" } string(27) "["G\u00fcnter, El\u00e8ne"]" string(27) "["G\u00fcnter, El\u00e8ne"]" string(27) "["G\u00fcnter, El\u00e8ne"]" string(19) "["Günter, Elène"]"
18array(1) { [0]=> string(1) "a" } string(5) "["a"]" string(5) "["a"]" string(5) "["a"]" string(5) "["a"]"
19array(1) { [0]=> array(1) { [0]=> int(1) } } string(5) "[[1]]" string(5) "[[1]]" string(5) "[[1]]" string(5) "[[1]]"
20array(2) { [2]=> bool(true) [3]=> bool(false) } string(20) "{"2":true,"3":false}" string(20) "{"2":true,"3":false}" string(20) "{"2":true,"3":false}" string(20) "{"2":true,"3":false}"
21array(1) { ["hello"]=> string(5) "world" } string(17) "{"hello":"world"}" string(17) "{"hello":"world"}" string(17) "{"hello":"world"}" string(17) "{"hello":"world"}"
22array(2) { ["hello"]=> bool(true) [0]=> string(5) "world" } string(26) "{"hello":true,"0":"world"}" string(26) "{"hello":true,"0":"world"}" string(26) "{"hello":true,"0":"world"}" string(26) "{"hello":true,"0":"world"}"
23array(3) { ["hello"]=> bool(true) [0]=> string(5) "hello" [1]=> string(5) "world" } string(38) "{"hello":true,"0":"hello","1":"world"}" string(38) "{"hello":true,"0":"hello","1":"world"}" string(38) "{"hello":true,"0":"hello","1":"world"}" string(38) "{"hello":true,"0":"hello","1":"world"}"
24array(2) { ["methodname"]=> string(5) "hello" ["params"]=> array(0) { } } string(34) "{"methodname":"hello","params":[]}" string(34) "{"methodname":"hello","params":[]}" string(34) "{"methodname":"hello","params":[]}" string(34) "{"methodname":"hello","params":{}}"
25array(2) { ["faultCode"]=> int(666) ["faultString"]=> string(11) "hello world" } string(45) "{"faultCode":666,"faultString":"hello world"}" string(45) "{"faultCode":666,"faultString":"hello world"}" string(45) "{"faultCode":666,"faultString":"hello world"}" string(45) "{"faultCode":666,"faultString":"hello world"}"
26array(3) { ["faultCode"]=> int(666) ["faultString"]=> string(11) "hello world" ["faultWhat?"]=> string(5) "dunno" } string(66) "{"faultCode":666,"faultString":"hello world","faultWhat?":"dunno"}" string(66) "{"faultCode":666,"faultString":"hello world","faultWhat?":"dunno"}" string(66) "{"faultCode":666,"faultString":"hello world","faultWhat?":"dunno"}" string(66) "{"faultCode":666,"faultString":"hello world","faultWhat?":"dunno"}"
27array(2) { ["faultCode"]=> int(666) ["faultString"]=> array(1) { [0]=> string(11) "hello world" } } string(47) "{"faultCode":666,"faultString":["hello world"]}" string(47) "{"faultCode":666,"faultString":["hello world"]}" string(47) "{"faultCode":666,"faultString":["hello world"]}" string(47) "{"faultCode":666,"faultString":["hello world"]}"
28array(2) { ["faultCode"]=> int(666) ["faultString"]=> array(1) { ["hello"]=> string(5) "world" } } string(49) "{"faultCode":666,"faultString":{"hello":"world"}}" string(49) "{"faultCode":666,"faultString":{"hello":"world"}}" string(49) "{"faultCode":666,"faultString":{"hello":"world"}}" string(49) "{"faultCode":666,"faultString":{"hello":"world"}}"

And the winner is...

Of course there cannot be a winner. Every lib test excels in some aspect and is surpassed in others.

The PHP native JSON extension cannot be beaten for speed, but it is very unforgiving on the json it parses as valid. A sure hit for almost everybody.

The Zend lib is the fastest of the php-based libs, and shows no major drawbacks, excepted for lack of support for php 4 (and a bug in encoding php objects). A solid recommendation for those on shared hosting or in the impossibility to install the extension.

The php-jsonrpc lib is the slowest of the pack at encoding php values (because of its object-centric two step conversion process), but sports more features than any other lib, such as automatic charset conversion or extra support for jsonrpc calls.
It is also the closest to the browsers javascript engines in its json parsing results.

The PEAR lib offers no clear advantage, but it still makes for a valid choice, providing the most forgiving json parser of all.

Changes

2006/11/17: fixed number of files used by PEAR and ZEND (they were swapped); added indication that PEAR lib assumes UTF8. Thanks to M. Migurski for pointing it out. Fixed links to comparison graphs.

댓글 없음: