Magento 2.2 serialization issues
After upgrading a Magento 2.1 instance to Magento 2.4, I realized some problems with serialized data. In Magento 2.1 PHPs serialize() and unserialize() functions have been used whilst in Magento 2.2 the default serialization uses json_encode() and json_decode().
For migrating the data, Magento comes with a Magento\Framework\DB\AggregatedFieldDataConverter implementation that contains the migration logic and a converter \Magento\Framework\DB\DataConverter\SerializedToJson to convert from PHP serialized data to JSON data.
The "problem" in our case was that the SerializedToJson implementation works under the assumption that all source data is serialized and thus can be converted via unserialize() and json_encode(). That was not the case in our specific setup, so I had to implement my own converter to fix this:
class SerializedToJson extends \Magento\Framework\DB\DataConverter\SerializedToJson
{
/**
* @param string $value
* @return string
* @throws \Magento\Framework\DB\DataConverter\DataConversionException
*/
public function convert($value)
{
if ($this->isValidJsonValue($value)) {
return $value;
}
try {
$value = $this->encodeJson($this->unserializeValue($value));
} catch (\Exception $e) {
}
return $value;
}
}
Basically, I added a try/catch block to catch any errors happening during the conversion. In that case, the original data gets returned as-is and won’t be changed.
In a setup script, you can now configure AggregatedFieldDataConverter to convert specific fields with the custom converter class defined above:
$fieldsToUpdate = [
new FieldToConvert(
SerializedToJson::class,
$setup->getTable('customer_eav_attribute'),
'attribute_id',
'validate_rules'
),
new FieldToConvert(
SerializedToJson::class,
$setup->getTable('core_config_data'),
'config_id',
'value'
),
];
$this->aggregatedFieldConverter->convert($fieldsToUpdate,
$setup->getConnection());