Bug #66581
closedExtbase - JsonView: wrong key encoding in array
100%
Description
If the array key is of type string, then the PHP function json_encode converts it to named objects instead of an array.
Extbase internal reference identifiers are encoded of type string instead of integer.
The bug is here in case of '_descendAll' https://github.com/TYPO3/TYPO3.CMS/blob/master/typo3/sysext/extbase/Classes/Mvc/View/JsonView.php#L255
FIX: convert the key to integer
Change from:
$array[$key] = $this->transformValue($element, $configuration['_descendAll']);
to:
$array[hexdec($key)] = $this->transformValue($element, $configuration['_descendAll']);
Updated by Andreas Allacher over 9 years ago
Is this abut e.g. objects in ObjectStorage?
If so, I think it might be best to check if there is a toArray method and call that beforehand because that way object storage converts itself to a numerical array which would be more correct.
ObjectStorage otherwise uses spl_object_hash as key.
Just removing the key itself is wrong because there can be other ArrayAccess objects that use "good" string values as keys which should not be "removed".
Updated by Andreas Allacher over 9 years ago
Maybe even better would be an interface for objectstorage that needs toArray that way it could be done with instanceof and would not be used classes that do something unexpected with toArray
Updated by Thilo Schumann over 9 years ago
To explain it a bit more:
I have setup in "Extension Builder" my own Ext. That Ext is very simple and something like: a list of companies, which has a 1:n relation to a list of daughters/sub-companies. Extbase itself generates internally an hexadecimal identifier for that. That identifier is encoded as a string value in Extbase instead of an integer value.
Then I want to export it in a JSON.
The PHP function json_encode() seems to encode an array with integer values as keys as an array, but an array with string values as keys are exported as named objects. As this "string" is only an internal reference of Extbase it makes no sense to export in JSON. So the key must be converted to integer before using the PHP function json_encode().
The above fix has a flaw, because hexdec() converts integer values to string. (Is here PHP broken? WTF!)
I changed the fix to:
if (is_int($key)) $array[$key] = $this->transformValue($element, $configuration['_descendAll']); else $array[hexdec($key)] = $this->transformValue($element, $configuration['_descendAll']);
Updated by Andreas Allacher over 9 years ago
Yes, that is true for ObjectStorage.
However, that might not be the case for other objects with ArrayAccess and just because most of the time extbase ArrayAccess objects will be used, doesn't mean that will be the case all the time.
So one would have to specifically handle ObjectStorage (and other corresponding) objects here.
Also the same loop is used for arrays which if they are not integer based most likely have important information in the keys.
The easist solution would be to check if the value has a method toArray and if so call that one. Or maybe even better create a corresponding interface (that requires toArray) for ObjectStorage and so on and implement it.
That way such objects (e.g. ObjectStorage) will be converted to an array with integer keys as index.
Regarding hexdec: I don't think it is a good idea to use hexdec anyway because according to php.net it can also return float values.
If one wants to ignore the key value which as mentioned might not be the case all the time, I would just use $array[] = ....
that way it will be added to an integer based array 0,1,.... which would be enough
Updated by Alexander Opitz about 8 years ago
- Status changed from Needs Feedback to Closed
No feedback within the last 90 days => closing this issue.
If you think that this is the wrong decision or experience this issue again, then please write to the mailing list typo3.teams.bugs with issue number and an explanation or open a new ticket and add a relation to this ticket number.
Updated by Markus Klein almost 2 years ago
- Status changed from Closed to Accepted
This is still the case even in v12.
At least the default ObjectStorage should work out of the box in the expected way.
(we have a dedicated JsonView in every extension, just because of this bug)
Updated by Gerrit Code Review almost 2 years ago
- Status changed from Accepted to Under Review
Patch set 1 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/77361
Updated by Gerrit Code Review almost 2 years ago
Patch set 2 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/77361
Updated by Markus Klein almost 2 years ago
- Status changed from Under Review to Resolved
- % Done changed from 0 to 100
Applied in changeset 65117663a5a300fba2acb00fa245565e1a41eb88.
Updated by Benni Mack almost 2 years ago
- Status changed from Resolved to Closed