The release of php 5.2.0, which includes by default an extension for converting php values from and to the JSON format, was a good occasion for comparing the different existing php libraries which aim to provide the same capabilities.
This page is an update of the original comparison, made to reflect the improvements that have been made by the various libraries.
The JSON homepage lists quite a few php libraries, but only 4 are in fact available for download and look stable and maintained:
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 evolving at a fast pace 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.
Since the original test, a new php library has come to my attention, implementing json encoding and decoding. It is part of the Solar php framework, and it is the third based on the original code from M. Migursky. It implements the same api as the php native extension, ans is contained within a single file. It has not been included in the test matrix for coherence with the previous tests, but might make it into future updates...
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 20th of April 2007 (read: CVS or unstable versions used where available)
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 | 20070420-4556 | CVS 1.31 2007/03/10 |
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 | Yes (php 5.2.1), No (pecl 1.2.1) | 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) up to php 5.2.0 only | 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 | Implements check to avoid infinite loop on recursive objects | Implements an optional (and somewhat problematic1) check to avoid infinite loop on recursive objects; if the json extensions is enabled, transparently takes advantage of it for faster operation2; has a slightly "twisted" way of encoding php objects3; uses Reflection to encode class definitions, too | Provides a compatibility layer that implement the same API as the PHP native json extension; adds support for the json-rpc webservice dialect |
|
Changes since last comparison | Changed to decode any json values as root elements, not just objects or arrays; added check to avoid infinite loop on recursive objects | none | added optional check to avoid infinite loop on recursive objects | fixes in decoding with application of charset transcoding |
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); |
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 4.4.5, 5.1.6 and 5.2.1 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 have 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 marginally slower than 5.1 on all libs except the xmlrpc one, despite the claims
made by the authors of it being much more optimized than its predecessors. Did I set it up wrong?
OTOH both versions of php 5 show a clear gain over the aging php 4.
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);
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.
Value4 | XmlRpc decoded | JS dec. | Native dec. | Pear dec. | Zend dec. | |
---|---|---|---|---|---|---|
0 | string(0) "" | NULL 'Invalid data (empty string?)' | NULL | NULL | NULL | |
1 | string(1) "1" | int(1) | int(1) | int(1) | int(1) | |
2 | string(4) "true" | bool(true) | bool(true) | bool(true) | bool(true) | |
3 | string(4) "null" | NULL | NULL | NULL | NULL | |
4 | string(7) ""hello"" | string(5) "hello" | string(5) "hello" | string(5) "hello" | string(5) "hello" | |
5 | string(11) "not a value" | NULL 'Invalid data' | string(11) "not a value" | NULL | NULL
'Illegal Token' | |
6 | string(2) "[]" | array(0) { } | array(0) { } | array(0) { } | array(0) { } | |
7 | string(3) "[1]" | array(1) { [0]=> int(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]=> 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]=> 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]=> float(1) } | array(1) { [0]=> float(1) } | array(1) { [0]=> float(1) } | |
11 | string(4) "[.5]" | NULL 'Invalid data' | 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]=> 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' | NULL | array(1) { [0]=> int(10) } | NULL
'Octal notation not supported by JSON (value: 010)' | |
20 | string(6) "[0xFF]" | array(1) { [0]=> int(255) } | NULL | array(1) { [0]=> int(0) } | NULL
'Illegal Token' | |
21 | string(6) "[0xff]" | array(1) { [0]=> int(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) } | |
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]=> 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) "" } | |
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" } | |
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" } | |
29 | string(4) "[1,]" | array(2) { [0]=> int(1) [1]=> NULL } | NULL | array(2) { [0]=> int(1) [1]=> NULL } | array(1) { [0]=> int(1) } | |
30 | string(3) "[,]" | array(2) { [0]=> NULL [1]=> NULL } | NULL | array(2) { [0]=> NULL [1]=> NULL } | array(1) { [0]=> NULL } | |
31 | string(4) "[,1]" | array(2) { [0]=> NULL [1]=> int(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) } | 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' | string(19) "// comment here [1]" | 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) } | string(19) "/*comment here*/[1]" | array(1) { [0]=> int(1) } | NULL
'Illegal Token' | |
38 | string(19) "[/*comment here*/1]" | array(1) { [0]=> int(1) } | NULL | array(1) { [0]=> int(1) } | NULL
'Illegal Token' | |
39 | string(19) "[1/*comment here*/]" | array(1) { [0]=> int(1) } | NULL | array(1) { [0]=> int(1) } | NULL
'Illegal Token' | |
40 | string(19) "[1]/*comment here*/" | array(1) { [0]=> int(1) } | NULL | array(1) { [0]=> int(1) } | NULL
'Illegal Token' | |
41 | string(7) "/**/[1]" | array(1) { [0]=> int(1) } | string(7) "/**/[1]" | NULL | NULL
'Illegal Token' | |
42 | string(6) "// [1]" | NULL 'Invalid data' | string(6) "// [1]" | 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?)' | 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" } | |
49 | string(5) "['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) "" } | 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) "'" } | |
60 | string(5) "['"']" | array(1) { [0]=> string(1) """ } | NULL | array(1) { [0]=> string(1) """ } | NULL
'Illegal Token' | |
61 | string(6) "["\'"]" | 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) "\'" } | |
63 | string(6) "["\""]" | 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) "\" } | |
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(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) " " } | 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) " " } | |
75 | string(12) "["\x41\xDC"]" | 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)#6 (0) { } } | array(1) { [0]=> array(0) { } } | array(1) { [0]=> array(0) { } } | |
80 | string(7) "[ { } ]" | array(1) { [0]=> array(0) { } } | array(1) { [0]=> object(stdClass)#5 (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) } } | 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)#5 (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)#6 (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)#6 (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)#5 (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) } } | 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) } } | 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) } } | 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) } } | 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) } } | 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) } } | 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) } } | 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) } } | NULL | array(1) { [0]=> array(1) { [1]=> int(1) } } | NULL
'Illegal Token' |
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(17) ""Gnter, El\u8ba5"" | 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\testsuite3.php on line 382 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(16) "application/json" ["payload"]=> NULL ["methodname"]=> string(5) "dummy" ["params"]=> array(0) { } ["debug"]=> int(0) } | string(104) "{"id":null,"content_type":"application\/json","payload":null,"methodname":"dummy","params":[],"debug":0}" | string(104) "{"id":null,"content_type":"application\/json","payload":null,"methodname":"dummy","params":[],"debug":0}" | string(104) "{"id":null,"content_type":"application\/json","payload":null,"methodname":"dummy","params":[],"debug":0}" | string(105) "{"__className":"jsonrpcmsg","content_type":"application/json","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"}}" |
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 some encoding quirks, that will undoubtely be fixed in future versions of the package). 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.
Comments, corrections, suggestions for improvement are welcome. A separate blog entry is available for dicussing this comparison.
2007/04/25: published the revised comparison page