4

I am working on a Silverstripe project and I would like to have a simple way to present the content of a CMS generated Page (or subtype of Page) as JSON.

Ideally, I would like to append "/json" at the end of the route, or send a parameter via post (json=true) and obtain a response in JSON format.

I tried adding an action to my CustomPage_Controller class like this:

public static $allowed_actions = array('json');
public function json(SS_HTTPRequest $request) {
    // ...
}

But I cannot figure out how to make that work:

  • What URL/Route should I use?
  • How do I get the content of the page?
argenkiwi
  • 2,134
  • 1
  • 23
  • 26
  • Needless to say this is the first time I use Silverstripe, so this could be a very basic question. However, after googling for a while I could not get the answer I am looking for. – argenkiwi Jul 04 '13 at 00:28

2 Answers2

10

You're on the right track. You'd simply do something like this in your json action:

public function json(SS_HTTPRequest $request) {

    $f = new JSONDataFormatter();
    $this->response->addHeader('Content-Type', 'application/json');
    return $f->convertDataObject($this->dataRecord);

}

Or for specific fields you could do this:

public function json(SS_HTTPRequest $request) {

    // Encode specific fields
    $data = array();
    $data['ID'] = $this->dataRecord->ID;
    $data['Title'] = $this->dataRecord->Title;
    $data['Content'] = $this->dataRecord->Content;

    $this->response->addHeader('Content-Type', 'application/json');
    return json_encode($data);

}

If you put the above inside the controller in your Page.php file and all your other pages extend Page_Controller then you should be able to go to http://mydomain/xxxx/json and get the JSON output for any page.

Shane Garelja
  • 1,428
  • 10
  • 10
  • 1
    You might want to add the appropriate content-type to the output. Like this: `$this->response->addHeader('Content-Type', 'application/json');` – bummzack Jul 07 '13 at 11:27
  • That worked like a charm. I was also having an issue with some HTML that is part of the JSON response, but adding the appropriate content type header, as @bummzack suggested, solved the issue. Thanks! – argenkiwi Jul 08 '13 at 02:06
  • Is this still a good answer in 2021 It seems JSONDataFormatter isnt in 4.x https://api.silverstripe.org/4/search.html?search=JSONDataFormatter – Daniel Tate Aug 25 '21 at 23:11
0

Shane's answer was helpful, however I needed to output all pages from a route, not just the current record.

Here is how I managed to do this :

<?php

class Page_Controller extends ContentController {

    private static $allowed_actions = [
        'index',
    ];

    public function init() {
        parent::init();
        // You can include any CSS or JS required by your project here.
        // See: http://doc.silverstripe.org/framework/en/reference/requirements
    }

    public function index(SS_HTTPRequest $request) {
        $results = [];
        $f = new JSONDataFormatter();
        foreach (Article::get() as $pageObj) {
            $results[] = $f->convertDataObjectToJSONObject($pageObj);
        }

        $this->response->addHeader('Content-Type', 'application/json');
        return json_encode($results);
    }
}