Не полагайтесь на порядок ключей в значениях MySQL JSON
Недавно я создавал простой дашборд, собирающий данные из upstream API и представляющий их в виде загружаемого CSV-отчёта для пользователя.
Частично цель заключалась в том, чтобы позволить API определить порядок и заголовки для каждого из столбцов данных. Я хранил бы полезную нагрузку из ответов API в одном столбце JSON в базе данных, чтобы позже использовать точное определение данных при сборке отчёта. Но я заметил, что порядок ключей массива строк не сохраняется при загрузке из базы данных.
// данные полученные из API
$payload = [
'first' => 'abc',
'middle' => 'jkl',
'last' => 'xyz',
];
// данные после загрузки из MySQL
$payload = [
'last' => 'xyz',
'first' => 'abc',
'middle' => 'jkl',
];
Я смог решить эту проблему, но мне стало интересно, почему это происходит. Это проблема сериализации PHP, декодирования/кодирования JSON, кастинга свойств Eloquent или что-то ещё?
Я покопался во всех слоях Laravel, но оказалось, что проблема кроется в MySQL. По соображениям производительности и согласованности, MySQL нормализует значения JSON при сохранении в базу данных.
Это объясняет, почему мои массивы перестраивались просто при сохранении и загрузке из базы данных!
И прежде чем вы начнёте полагаться на конкретную стратегию нормализации, которую использует MySQL, ознакомьтесь с этим предупреждением из документации:
Вы должны знать, что результат этого упорядочивания может быть изменён и не гарантируется, что он будет последовательным в разных релизах.
В целом, совет никогда не полагаться на определённый порядок ключей — хороший совет, который стоит запомнить. Если порядок действительно важен, убедитесь, что он явно отслеживается каким-то другим способом.