Try this query:
SELECT array_to_json(array_agg(t)) FROM t
The result is the following JSON:
[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]
Here's SQLFiddle: http://sqlfiddle.com/#!15/5860d/11/0 . The SQLFiddle results have some weird thing called "Value" / "Type" that happens in the JSON object and it eludes the result line (which maps to "Value" ), but it doesn't seem to happen when running on a simple PostgreSQL, It looks like it's some kind of SQLFiddle quirk.
As for good design or not depending on your specific application. Overall, benchmarking would be the best way to tell if this works for you in terms of performance. As for maintainability, I do not see any particular problems. On the contrary. This simplifies your application code and means that it is smaller, at least in my opinion. If PG can give you exactly the result you need out of the box, the only reason I can think not to use it is for performance reasons. Do not reinvent the wheel and thatβs it.
Edit:
I did not understand that you are looking for queries for both results.
First, for your second result, you can use:
SELECT row_to_json(r) FROM (SELECT array_agg(ta) AS a , array_agg(tb) AS b FROM t ) r
The subquery allows you to manage key names in the resulting JSON object. This gives
{"a":[1,2,3],"b":["value1","value2","value3"]}
SQLFiddle: http://sqlfiddle.com/#!15/5860d/42/0
Secondly, in my digging, I found a couple of other functions introduced in 9.3 that you should consider:
1) json_agg : this does what you want for your first result out of the box.
SELECT json_agg(t) FROM t
SQLFiddle: http://sqlfiddle.com/#!15/5860d/38/0
2) to_json : This can be used instead of array_to_json or row_to_json and gives the same results.
SELECT to_json(array_agg(t)) FROM t
SQLFiddle: http://sqlfiddle.com/#!15/5860d/10/0