microformats/php-mf2

No rels leads to empty array rather than empty object in output

tommorris opened this issue · 3 comments

This is probably unfixable because of PHP, but I wanted to file it so it is on record.

If you parse a document that has no rels, you get back an empty JSON array in the json_encoded output. If you parse a document that has rels, you get back a JSON object. The specification says you should get back an empty object.

Obviously, in PHP lists and dictionaries (in Python terminology) are unified into array which can represent both list-style arrays (numerically-keyed arrays in PHP), dictionary-style arrays (associative arrays) and mixed list and dictionary style. json_encode lets you specify a flag for how you encode empty arrays.

One possible solution to this is to json_encode each piece separately and then stitch them together. Or just ignore the problem and operate on the basis that PHP will never quite be spec-compliant.

Thanks for filing, might be fixable by using new stdclass (empty generic object) instead of an array if there are no rel values.

Full timeline of this issue (for reference):

2013-09-15: Tom Morris reports the issue. Parser incorrectly serialises empty rels.
2013-09-15: Barnaby Walters closes the issue with 91c171b, a hard-coded change of an empty rels array to a new stdClass. Parser correctly serialises empty rels.
Version 0.2.5: previous hard-coded change removed to prevent errors when using empty rel stdClasses in code. Parser incorrectly serialises empty rels.
2014-04-07 (version 0.2.6): Barnaby Walters adds JSON-mode with 28bd4d5, allowing people who want to parse microformats specifically for JSON serialisation to have the switch performed. Parser can correctly serialise empty rels if JSON-mode enabled.

@aaronpk suggested possibly using ArrayObject instead of stdClass (alleviating the need for a jsonMode switch). Initial testing seems like this might work as expected for both encoding and iterating.

php > echo json_encode(["rels" => new ArrayObject()]);
{"rels":{}}
php > foreach (new ArrayObject() as $k => $v) { echo $k; }
php > 

down-side is actual array_* methods don't work like

php > $arr = new ArrayObject();
php > var_dump( array_keys($arr) );
PHP Warning:  array_keys() expects parameter 1 to be array, object given in php shell code on line 1