Remove resource wrapper from CakePHP REST API JSON

257 views Asked by At

My question is similar to this one. I understand the answer given there. The OP of that question doesn't seem to have my issue.

I am using CakePHP 2.2.3. I am fetching a resource like this:

http://cakephpsite/lead_posts.json

and it returns results like this:

[
    {
        "LeadPost": {
            "id": "1",
            "fieldA": "blah",
            "fieldB": "blah2",
        }
    {
        "LeadPost": {
            "id": "1",
            "fieldA": "blah",
            "fieldB": "blah2"
        }
    }
]

See the LeadPost wrapper on each object? I'm not sure why it's there. I want to remove it.

The LeadPost model extends AppModel and is otherwise empty.

LeadPostsController.php

class LeadPostsController extends AppController {

    public $components = array('RequestHandler');

    public function index() {
        $records = $this->LeadPost->find('all', ['limit' => 20]);
        $this->set(array(
            'leadposts' => $records,
            '_serialize' => 'leadposts'
        ));
    }
}

My routing is very simple:

Router::mapResources('lead_posts');
Router::parseExtensions();
2

There are 2 answers

4
drmonkeyninja On BEST ANSWER

Use the Hash utility to rewrite the results returned before setting the data for the View:-

class LeadPostsController extends AppController {

    public $components = array('RequestHandler');

    public function index() {
        $records = $this->LeadPost->find('all', ['limit' => 20]);
        $this->set(array(
            'leadposts' => Hash::extract($records, '{n}.LeadPost'),
            '_serialize' => 'leadposts'
        ));
    }
}

Here Hash::extract($records, '{n}.LeadPost') will rewrite your array so that the LeadPost index is removed. It won't maintain the original array indexes, but unless you've messed with them in an afterFind callback should be the same.

You could do this in the Model's afterFind as burzum suggests, but it feels more natural to me to do this in the Controller as we are specifically preparing the data for the View.

1
floriank On

You have two options:

  1. Use the afterFind() model callback to reformat the standard data structure. But this will be reformatted for other calls as well then.
  2. Or use JSON views.

Two will be basically the same as one except that you move the logic in the view file. The 2nd option is the better one because of this.