JSON view example from docs gives "Missing Template error"

I am trying to output json. using the example in the docs here https://book.cakephp.org/4/en/views/json-and-xml-views.html

Going to the following URL gives me a missing template error. I just want the json I dont want to use a template

http://localhost:8765/Articles/index

What am I doing wrong?


namespace App\Controller;

use Cake\View\JsonView;

class ArticlesController extends AppController
{
    public function viewClasses(): array
    {
        return [JsonView::class];
    }

    public function index()
    {
        // Some code that created $articles and $comments
        $articles = [
            "one" => "Article 1",
            "two" => "Article 2",
            "three" => "Article 3",
            "four" => "Article 4",

        ];
        // Set the view vars that have to be serialized.
        $this->set("articles",$articles);

        // Specify which view vars JsonView should serialize.
        $this->viewBuilder()->setOption('serialize', 'articles');
    }
}

I found the issue missing a line in the Docs

$this->viewBuilder()->setClassName("Json");
1 Like

in 3.1 when you don’t want template
$this->autoRender = false;
helps

@Jubbs You should know that the way how content type negotiation works is not only decided by the server but also by the client.

So in the example of the docs you are only adding the possibility of a JSON content type to your controller actions via

public function viewClasses(): array
{
    return [JsonView::class];
}

and

$this->viewBuilder()->setOption('serialize', 'articles');

inside your action.

But this doesn’t mean it is forced to only be JSON, it can still be a simple HTTP request with the default template which returns HTML.

If you want JSON as a response your client should specify it wants JSON via the Accept Header which should be set to application/json

It of course depends on what client you are using, in e.g. jQuery it is the option dataType: 'json',
In Postman you can set additional headers easily like so


and many many more possibilites of course.

You can alternativly add

$routes->setExtensions(['json']);

to your config/routes.php (or plugin routes) to allow JSON routes.
This means, that you can e.g. call your action via

http://localhost/mycontroller/myaction/3.json

instead of

http://localhost/mycontroller/myaction/3

and get a direct JSON response without having the need to manually set the JSON View Class via

$this->viewBuilder()->setClassName("Json");

Thanks, @Jubbs ! This was tripping me up as well.