<?php
$listOfIntegers = [1, 2, 3, 4];
$myObject = new stdClass();
$myObject->integers = $listOfIntegers;
echo json_encode($myObject) . PHP_EOL;
// Output of the code above will be: `{"integers":[1,2,3,4]}`
// Now some refactoring has to be made since the requirement changed. The requirement now is that the integers list
// must not contain odd values anymore. So `array_filter` to the rescue, right?
$listOfEvenIntegers = array_filter([1, 2, 3, 4], static fn (int $integer): int => $integer % 2 === 0);
$myObject = new stdClass();
$myObject->integers = $listOfEvenIntegers;
echo json_encode($myObject) . PHP_EOL;
// Output of the refactored code above now became: `{"integers":{"1":2,"3":4}}`
// So what now happened is a huge problem for highly type-sensitive API clients since we changed a list to a hashmap
// Same happens with hashmaps which suddenly become empty.
$hashmap = [
'foo' => 'bar',
];
$myObject = new stdClass();
$myObject->map = $hashmap;
echo json_encode($myObject) . PHP_EOL;
// Output of the code above will be: `{"map":{"foo":"bar"}}`
// So now some properties are being added, some are being removed, the definition of your API says
// "the object will contain additional properties because heck I do not want to declare every property"
// "so to make it easier, every property has a string value"
// can be easily done with something like this in JSONSchema: `{"type": "object", "additional_properties": {"type": "string"}}`
// Now, some string value might become `null` due to whatever reason, lets say it was a bug and thus the happy path always returned a string
// The most logical way here is, due to our lazyness, to use something like `array_filter` to get rid of all our non-string values
$hashmap = [
'foo' => null,
];
$myObject = new stdClass();
$myObject->map = array_filter($hashmap);
echo json_encode($myObject) . PHP_EOL;
// Output of the refactored code above now became: `{"map":[]}`
// So in case that every array value is being wiped due to the filtering, we suddenly have a type-change from
// a hashmap to a list. This is ofc also problematic since we do not want to have a list here but an empty object like
// so: `{"map":{}}`
Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).