The derived table is necessary to keep the column names as attribute names in the JSON document. I also replaced your ancient, outdated and fragile implicit join in the WHERE clause with an explicit JOIN operator.

If you need to process the result as a plain text value, you can cast it using json_agg(row_to_json(x))::text