Как избавиться от try-catch в контроллерах?
Смотря для чего вы делаете эти try catch. Это не всегда повторяемость иногда действительно нужна, например, чтобы перебросить своё исключение. Пойти можно разными способами. Но а простой - это вам нужно просто их убрать и сделать Listener или Subscriber, который будет обрабатывать ошибки и отдавать их в нужном формате в api. Если правильно понял для чего нужно. Пример.
сделать мидлвар/слушатель, который вокруг контроллера, но просто его в коде не видно, он как правило часть фреймворка. или в index.php обернуть require что-то в try catch в одном единственном месте

try catch это же "поставить следилку, закрыть следилку, что делать с отслеживаемым". Не пиши их и их не будет. Респонсы ифами генерируй "if (! $content) return new JsonResponse();". А то что вы хотите эксепшен выбросить как JSON это не про конкретный трайкетч, это про "обработка ошибок в рамке папки с контроллерами по имени api/v1/"