La migliore soluzione che ho trovato è usare JSON_MERGE() in combinazione con JSON_OBJECT() e CONCAT()
SELECT
T1.id,
CONCAT(
'{"elements": [',
GROUP_CONCAT(
JSON_MERGE(
JSON_OBJECT(
'type', T2.`type`,
'data', T2.`data`
),
CONCAT('{"info": ', T2.`info`, '}')
)
),
']}'
) AS `elements`,
FROM `table` T1
INNER JOIN `table2` T2
ON T1.`id` = T2.`fk_t1_id`
GROUP BY T1.`id`