Спустя три дня поиска все-таки пришел к такому решению, может кому-то будет полезно:
SELECT "social_id", json_agg(json_build_object('type', type, 'token', token) AS "socials" FROM "socials" WHERE "user_id" = 105 GROUP BY "social_id";
json_build_object принимает в качестве аргументов имя ключа для объекта и значение (имя ключа в таблице) через запятую.
Результат:
[
{ type: 2, token: 'something2' },
{ type: 1, token: 'something' }
]
Остается только объединить с запросом выше, чтобы социальные сети выводились таким образом при запросе данных пользователя.
Важно указать все ключи из таблицы пользователя в ORDER BY, иначе снова начнется дублирование.