It is not optimized. Each column name, as a JSON key, is sent in full, multiple times. You could try connecting over SSL and turning on compression, but for security reasons that is disabled by default in most systems, and is getting increasingly difficult to turn on.
If the column names are really reapeated once per row, we would spend more bandwith ...
Instead of looking on the json functions docs page, look instead on the aggregate functions docs page. jsonb_object_agg() will aggregate the object without an additional level of nesting as seen in this demo.
jsonb_object_agg(c.name,json_build_object('d1',d.d1,'d2',d.d2)) as b
join d on d.id = b_d.d_id
join c on c.id = d....
You could extract the values from the JSONB value and aggregate them back into a JSON array
select 'some_table' as table_name,
(select jsonb_agg(x.v) from jsonb_each(to_jsonb(t) - 'id') as x(k,v)) as content
from some_table t;
But you can't rely that the order of the array elements corresponds to the order of the columns in the table.