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 lib written originally by Omar Kilani is the one that is now officially part of PHP
- The JSON lib, orginally written by M. Migurski and now officially part of PEAR
- The Zend_Json lib, which is part of the Zend Framework
- The Jsonrpc (and Json) extension to the php-xmlrpc lib (written by yours truly)
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.
Feature | PHP Json | Pear Json | Zend json | XmlRpc json |
---|---|---|---|---|
Version | 1.2.1 2006/03/31 | 1.31 2006/06/28 | 20061105-1470 | CVS Id 1.25 2006/11/05 |
PHP version compatibility | 4 (for windows the dll for php 4.3 and above is availabale on pecl4win), 5 | 4.0.6, 5 | 5 | 4.2, 5 |
PHP files used | 0 | 1 | 6 | 2 |
Encodes to 7-bit ASCII clean JSON strings, using unicode escape sequences | Yes | Yes | No | Yes |
Supports encoding php strings from different charsets | Assumes UTF-8 | Assumes UTF-8 | Does not convert string data: it is up to the user to take care about conversion to the desired charset | UTF-8, ISO-8859-1, ASCII |
Supports decoding JSON data that has not an an array or object as top level element | No | Yes | Yes | Yes |
Supports decoding JSON objects as either php arrays or objects | Yes | Yes | Yes | Yes |
Supports distinguishing a failed decoding from decoding a single NULL value | Yes (single NULL value cannot be decoded) | No | Yes (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 accepted | Parses almost everything as valid (within an array) | Some | Tries 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
Goal | PHP Json | Pear Json | Zend json | XmlRpc 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).
|
|
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
Value | XmlRpc decoded | JS dec. | Native dec. | Pear dec. | Zend dec. | |
---|---|---|---|---|---|---|
0 | string(0) "" | NULL 'Invalid data (empty string?)' | NULL | NULL | NULL | NULL |
1 | string(1) "1" | int(1) | number(1) | NULL | int(1) | int(1) |
2 | string(4) "true" | bool(true) | bool(true) | NULL | bool(true) | bool(true) |
3 | string(4) "null" | NULL | NULL | NULL | NULL | NULL |
4 | string(7) ""hello"" | string(5) "hello" | string(5) "hello" | NULL | string(5) "hello" | string(5) "hello" |
5 | string(11) "not a value" | NULL 'Invalid data' | NULL | NULL | NULL 'Illegal Token' | |
6 | string(2) "[]" | array(0) { } | array(0) { } | array(0) { } | array(0) { } | array(0) { } |
7 | string(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) } |
8 | string(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) } |
9 | string(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) } |
10 | string(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) } |
11 | string(4) "[.5]" | NULL 'Invalid data' | array(1) { [0]=> number(0.5) } | NULL | array(1) { [0]=> float(0.5) } | array(1) { [0]=> float(0.5) } |
12 | string(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) } |
13 | string(3) "[.]" | NULL 'Invalid data' | NULL | array(1) { [0]=> NULL } | NULL 'Illegal number format: .' | |
14 | string(6) "[5..5]" | NULL 'Invalid data' | NULL | array(1) { [0]=> NULL } | NULL 'Missing "," in array encoding: [5..5]' | |
15 | string(5) "[10e]" | NULL 'Invalid data' | NULL | array(1) { [0]=> NULL } | NULL 'Illegal Token' | |
16 | string(5) "[e10]" | NULL 'Invalid data' | NULL | array(1) { [0]=> NULL } | NULL 'Illegal Token' | |
17 | string(7) "[010e2]" | NULL 'Invalid data' | NULL | array(1) { [0]=> float(1000) } | array(1) { [0]=> float(1000) } | |
18 | string(7) "[010.2]" | NULL 'Invalid data' | NULL | array(1) { [0]=> float(10.2) } | array(1) { [0]=> float(10.2) } | |
19 | string(5) "[010]" | NULL 'Invalid data' | array(1) { [0]=> number(8) } | NULL | array(1) { [0]=> int(10) } | array(1) { [0]=> int(10) } |
20 | string(6) "[0xFF]" | array(1) { [0]=> int(255) } | array(1) { [0]=> number(255) } | NULL | array(1) { [0]=> int(0) } | NULL 'Illegal Token' |
21 | string(6) "[0xff]" | array(1) { [0]=> int(255) } | array(1) { [0]=> number(255) } | NULL | array(1) { [0]=> int(0) } | NULL 'Illegal Token' |
22 | string(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) } |
23 | string(6) "[TRUE]" | array(1) { [0]=> bool(true) } | NULL | array(1) { [0]=> bool(true) } | NULL 'Illegal Token' | |
24 | string(6) "[null]" | array(1) { [0]=> NULL } | array(1) { [0]=> undefined } | array(1) { [0]=> NULL } | array(1) { [0]=> NULL } | array(1) { [0]=> NULL } |
25 | string(6) "[NULL]" | array(1) { [0]=> NULL } | NULL | array(1) { [0]=> NULL } | NULL 'Illegal Token' | |
26 | string(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) "" } |
27 | string(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" } |
28 | string(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" } |
29 | string(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) } |
30 | string(3) "[,]" | array(2) { [0]=> NULL [1]=> NULL } | array(1) { [0]=> undefined } | NULL | array(2) { [0]=> NULL [1]=> NULL } | array(1) { [0]=> NULL } |
31 | string(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) } |
32 | string(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) } |
33 | string(19) "// comment here [1]" | NULL 'Invalid data' | NULL | array(1) { [0]=> int(1) } | NULL 'Illegal Token' | |
34 | string(19) "[// comment here 1]" | NULL 'Invalid data' | NULL | array(1) { [0]=> int(1) } | NULL 'Illegal Token' | |
35 | string(19) "[1// comment here ]" | NULL 'Invalid data' | NULL | array(1) { [0]=> NULL } | NULL 'Illegal Token' | |
36 | string(19) "[1]// comment here " | NULL 'Invalid data (array missing closing bracket?)' | NULL | NULL | NULL 'Illegal Token' | |
37 | string(19) "/*comment here*/[1]" | array(1) { [0]=> int(1) } | array(1) { [0]=> number(1) } | NULL | array(1) { [0]=> int(1) } | NULL 'Illegal Token' |
38 | string(19) "[/*comment here*/1]" | array(1) { [0]=> int(1) } | array(1) { [0]=> number(1) } | NULL | array(1) { [0]=> int(1) } | NULL 'Illegal Token' |
39 | string(19) "[1/*comment here*/]" | array(1) { [0]=> int(1) } | array(1) { [0]=> number(1) } | NULL | array(1) { [0]=> int(1) } | NULL 'Illegal Token' |
40 | string(19) "[1]/*comment here*/" | array(1) { [0]=> int(1) } | array(1) { [0]=> number(1) } | NULL | array(1) { [0]=> int(1) } | NULL 'Illegal Token' |
41 | string(7) "/**/[1]" | array(1) { [0]=> int(1) } | array(1) { [0]=> number(1) } | NULL | NULL | NULL 'Illegal Token' |
42 | string(6) "// [1]" | NULL 'Invalid data' | NULL | NULL | NULL 'Illegal Token' | |
43 | string(20) "[1 // comment here ]" | NULL 'Invalid data' | NULL | array(1) { [0]=> int(1) } | NULL 'Illegal Token' | |
44 | string(20) "[ // comment here 1]" | NULL 'Invalid data' | NULL | array(1) { [0]=> int(1) } | NULL 'Illegal Token' | |
45 | string(18) "[1]// comment here" | NULL 'Invalid data (array missing closing bracket?)' | array(1) { [0]=> number(1) } | NULL | NULL | NULL 'Illegal Token' |
46 | string(19) "[1] // comment here" | NULL 'Invalid data (array missing closing bracket?)' | NULL | array(1) { [0]=> int(1) } | NULL 'Illegal Token' | |
47 | string(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" } | |
48 | string(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" } |
49 | string(5) "['a']" | array(1) { [0]=> string(1) "a" } | array(1) { [0]=> string(1) "a" } | NULL | array(1) { [0]=> string(1) "a" } | NULL 'Illegal Token' |
50 | string(4) "["a]" | NULL 'Invalid data (string missing closing quote?)' | NULL | array(1) { [0]=> NULL } | array(1) { [0]=> string(2) "a]" } | |
51 | string(4) "[a"]" | NULL 'Invalid data (string missing closing quote?)' | NULL | array(1) { [0]=> NULL } | NULL 'Illegal Token' | |
52 | string(5) "['a"]" | NULL 'Invalid data (string missing closing quote?)' | NULL | array(1) { [0]=> NULL } | NULL 'Illegal Token' | |
53 | string(5) "["a']" | NULL 'Invalid data (string missing closing quote?)' | NULL | array(1) { [0]=> NULL } | array(1) { [0]=> string(3) "a']" } | |
54 | string(3) "[']" | NULL 'Invalid data (string missing closing quote?)' | NULL | array(1) { [0]=> NULL } | NULL 'Illegal Token' | |
55 | string(4) "['']" | array(1) { [0]=> string(0) "" } | array(1) { [0]=> string(0) "" } | NULL | array(1) { [0]=> string(0) "" } | NULL 'Illegal Token' |
56 | string(5) "[''']" | NULL 'Invalid data (string missing closing quote?)' | | NULL | array(1) { [0]=> NULL } | NULL 'Illegal Token' |
57 | string(3) "["]" | NULL 'Invalid data (string missing closing quote?)' | NULL | array(1) { [0]=> NULL } | array(1) { [0]=> string(1) "]" } | |
58 | string(5) "["""]" | NULL 'Invalid data (string missing closing quote?)' | NULL | array(1) { [0]=> NULL } | NULL 'Missing "," in array encoding: ["""]' | |
59 | string(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) "'" } |
60 | string(5) "['"']" | array(1) { [0]=> string(1) """ } | array(1) { [0]=> string(1) """ } | NULL | array(1) { [0]=> string(1) """ } | NULL 'Illegal Token' |
61 | string(6) "["\'"]" | array(1) { [0]=> string(1) "'" } | array(1) { [0]=> string(1) "'" } | NULL | array(1) { [0]=> string(1) "'" } | NULL 'Illegal escape sequence '''' |
62 | string(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) "\'" } |
63 | string(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) """ } |
64 | string(5) "["\"]" | NULL 'Invalid data (string missing closing quote?)' | NULL | array(1) { [0]=> string(1) "\" } | array(1) { [0]=> string(2) ""]" } | |
65 | string(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) "\" } |
66 | string(7) "["\\\"]" | NULL 'Invalid data (string missing closing quote?)' | NULL | array(1) { [0]=> string(2) "\\" } | array(1) { [0]=> string(3) "\"]" } | |
67 | string(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" } | |
68 | string(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" } | |
69 | string(6) "["a "]" | NULL 'Invalid data (line terminator char inside string?)' | NULL | array(1) { [0]=> string(1) "a" } | array(1) { [0]=> string(2) "a " } | |
70 | string(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" } | |
71 | string(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" } | |
72 | string(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'' |
73 | string(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'' |
74 | string(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) " " } |
75 | string(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'' |
76 | string(7) "[ ] [ ]" | NULL 'Invalid data (unmatched array closing bracket?)' | NULL | array(1) { [0]=> NULL } | array(0) { } | |
77 | string(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"]' | |
78 | string(5) "[1 2]" | NULL 'Invalid data' | NULL | array(1) { [0]=> NULL } | NULL 'Missing "," in array encoding: [1 2]' | |
79 | string(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) { } } |
80 | string(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) { } } |
81 | string(5) "[{1}]" | NULL 'Invalid data (missing object member name?)' | NULL | array(1) { [0]=> array(0) { } } | NULL 'Missing key in object encoding: [{1}]' | |
82 | string(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}]' |
83 | string(6) "[{:1}]" | NULL 'Invalid data (missing object member name?)' | | NULL | array(1) { [0]=> array(0) { } } | NULL 'Missing key in object encoding: [{:1}]' |
84 | string(8) "[{"1":}]" | NULL 'Invalid data (empty string?)' | NULL | array(1) { [0]=> array(0) { } } | array(1) { [0]=> array(1) { [1]=> NULL } } | |
85 | string(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) } } |
86 | string(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) } } |
87 | string(8) "[{"a":}]" | NULL 'Invalid data (empty string?)' | NULL | array(1) { [0]=> array(0) { } } | array(1) { [0]=> array(1) { ["a"]=> NULL } } | |
88 | string(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) } } |
89 | string(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) } } |
90 | string(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}]' |
91 | string(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}]' |
92 | string(11) "[{a "a":1}]" | array(1) { [0]=> array(1) { ["a "a""]=> int(1) } } | NULL | array(1) { [0]=> array(0) { } } | NULL 'Illegal Token' | |
93 | string(12) "[{"a":1"a"}]" | NULL 'Invalid data' | NULL | array(1) { [0]=> array(1) { ["a"]=> NULL } } | NULL 'Missing "," in object encoding: [{"a":1"a"}]' | |
94 | string(11) "[{a b:"a"}]" | array(1) { [0]=> array(1) { ["a b"]=> string(1) "a" } } | NULL | array(1) { [0]=> array(0) { } } | NULL 'Illegal Token' | |
95 | string(11) "[{a b:a b}]" | NULL 'Invalid data' | NULL | array(1) { [0]=> array(0) { } } | NULL 'Illegal Token' | |
96 | string(11) "[{a 1:a 1}]" | NULL 'Invalid data' | NULL | array(1) { [0]=> array(0) { } } | NULL 'Illegal Token' | |
97 | string(9) "[{a:b:c}]" | NULL 'Invalid data' | NULL | array(1) { [0]=> array(1) { ["a"]=> NULL } } | NULL 'Illegal Token' | |
98 | string(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' |
99 | string(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' |
100 | string(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' |
101 | string(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' |
102 | string(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' |
103 | string(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
Value | XmlRpc encoded | Native enc. | Pear enc. | Zend enc. | |
---|---|---|---|---|---|
0 | bool(true) | string(4) "true" | string(4) "true" | string(4) "true" | string(4) "true" |
1 | bool(false) | string(5) "false" | string(5) "false" | string(5) "false" | string(5) "false" |
2 | int(0) | string(1) "0" | string(1) "0" | int(0) | string(1) "0" |
3 | int(1) | string(1) "1" | string(1) "1" | int(1) | string(1) "1" |
4 | float(1) | string(3) "1.0" | string(1) "1" | float(1) | string(1) "1" |
5 | float(1.1) | string(3) "1.1" | string(3) "1.1" | float(1.1) | string(3) "1.1" |
6 | string(0) "" | string(2) """" | string(2) """" | string(2) """" | string(2) """" |
7 | NULL | string(4) "null" | string(4) "null" | string(4) "null" | string(4) "null" |
8 | string(1) "1" | string(3) ""1"" | string(3) ""1"" | string(3) ""1"" | string(3) ""1"" |
9 | string(17) "20060101T12:00:00" | string(19) ""20060101T12:00:00"" | string(19) ""20060101T12:00:00"" | string(19) ""20060101T12:00:00"" | string(19) ""20060101T12:00:00"" |
10 | string(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"" |
11 | string(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"" |
12 | resource(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" |
13 | string(8) "aGVsbG8=" | string(10) ""aGVsbG8="" | string(10) ""aGVsbG8="" | string(10) ""aGVsbG8="" | string(10) ""aGVsbG8="" |
14 | object(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}" |
15 | object(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}" |
16 | array(0) { } | string(2) "[]" | string(2) "[]" | string(2) "[]" | string(2) "{}" |
17 | array(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"]" |
18 | array(1) { [0]=> string(1) "a" } | string(5) "["a"]" | string(5) "["a"]" | string(5) "["a"]" | string(5) "["a"]" |
19 | array(1) { [0]=> array(1) { [0]=> int(1) } } | string(5) "[[1]]" | string(5) "[[1]]" | string(5) "[[1]]" | string(5) "[[1]]" |
20 | array(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}" |
21 | array(1) { ["hello"]=> string(5) "world" } | string(17) "{"hello":"world"}" | string(17) "{"hello":"world"}" | string(17) "{"hello":"world"}" | string(17) "{"hello":"world"}" |
22 | array(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"}" |
23 | array(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"}" |
24 | array(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":{}}" |
25 | array(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"}" |
26 | array(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"}" |
27 | array(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"]}" |
28 | array(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.
댓글 없음:
댓글 쓰기