# Response with JSON scheme

**URL:** <https://discourse.slimframework.com/t/response-with-json-scheme/776>\
**Category:** Questions\
**Created:** [October 5, 2016, 5:49pm UTC](https://discourse.slimframework.com/t/response-with-json-scheme/776 "2016-10-05T17:49:38Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![AndersonDev](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/andersondev/32/50_2.png) [@AndersonDev](https://discourse.slimframework.com/u/AndersonDev)\
**Post date:** [October 5, 2016, 5:49pm UTC](https://discourse.slimframework.com/t/response-with-json-scheme/776/1 "2016-10-05T17:49:39Z")

</div>

Hi. I have the following scheme of json responses:  
`{`  
`"status": "success",`  
`"data": {`  
`},`  
`"message": null`}`  
And HTML Codes.

Now I doing like this:  
`$response->withJson(array('status' => 'error', 'data' => null, 'message' => 'Incorrect username or password'), 404);`  
or  
`$data = array('token' => $jwtToken);`  
`return $response->withJson(array('status' => 'success', 'data' => $data, 'message' => null));`

I need to copy this every 500 responses in 40 controllers. I want something elegant:  
`$response->withSJson($data);`  
or for error:  
`$response->withSJson('Lecturer not exist', 404);`

How to realize that?

---

<div class="post-metadata">

**Author:** ![alnorth](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/alnorth/32/204_2.png) [@alnorth](https://discourse.slimframework.com/u/alnorth)\
**Post date:** [October 6, 2016, 2:49pm UTC](https://discourse.slimframework.com/t/response-with-json-scheme/776/2 "2016-10-06T14:49:40Z")

</div>

We use a similar sort of response structure and we’ve implemented it by subclassing the `Response` class and injecting it into Slim.

So, you’d need your own response class like this:

```
use Psr\Http\Message\ServerRequestInterface as Request;

class MyResponse extends \Slim\Http\Response {

  public function withJson($data, $status = null, $encodingOptions = 0) {
    if(!isset($data['error'])) {
      $data['error'] = false;
    }

    if(!isset($data['status'])) {
      $data['status'] = $status ?: $this->getStatusCode();
    }

    return parent::withJson($data, $status, $encodingOptions);
  }

  public function withJsonData($data) {
    return $this->withJson([
      'data' => $data
    ]);
  }
}

```

And then inject it like this (which is an altered copy of the `response` value that’s set by default):

```
$slimContainer = new \Slim\Container();

// Use our Response class instead of the default. This sets some extra values on JSON responses.
$slimContainer['response'] = function ($slimContainer) {
  $headers = new Headers(['Content-Type' => 'text/html; charset=UTF-8']);
  $response = new MyResponse(200, $headers);

  return $response->withProtocolVersion($slimContainer->get('settings')['httpVersion']);
};

$app = new \Slim\App($slimContainer);

```

Of course you’ll need to update the `MyResponse` class to match your particular response structure.

---

<div class="post-metadata">

**Author:** ![alono](https://avatars.discourse-cdn.com/v4/letter/a/d2c977/32.png) [@alono](https://discourse.slimframework.com/u/alono)\
**Post date:** [October 6, 2016, 3:04pm UTC](https://discourse.slimframework.com/t/response-with-json-scheme/776/3 "2016-10-06T15:04:29Z")

</div>

Another way to go about is to create a base controller with a protected response method which all your controllers extends that base controller.  
By doing so you call $this-\>res($data [, $status]);  
Good luck

---

<div class="post-metadata">

**Author:** ![AndersonDev](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/andersondev/32/50_2.png) [@AndersonDev](https://discourse.slimframework.com/u/AndersonDev)\
**Post date:** [October 7, 2016, 10:22pm UTC](https://discourse.slimframework.com/t/response-with-json-scheme/776/4 "2016-10-07T22:22:27Z")

</div>

Works good? It is normal style?

---

<div class="post-metadata">

**Author:** ![alnorth](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/alnorth/32/204_2.png) [@alnorth](https://discourse.slimframework.com/u/alnorth)\
**Post date:** [October 7, 2016, 10:48pm UTC](https://discourse.slimframework.com/t/response-with-json-scheme/776/5 "2016-10-07T22:48:59Z")

</div>

That I don’t know. To me it feels like the cleanest way to go about this,  
and just extends the precedent set by methods like withRedirect on the  
existing Slim Response class. However, it’s possible that using the  
dependency injection in this way makes the code a little vulnerable to  
future changes in Slim.

---

<div class="post-metadata">

**Author:** ![AndersonDev](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/andersondev/32/50_2.png) [@AndersonDev](https://discourse.slimframework.com/u/AndersonDev)\
**Post date:** [October 7, 2016, 11:06pm UTC](https://discourse.slimframework.com/t/response-with-json-scheme/776/6 "2016-10-07T23:06:39Z")

</div>

You right. But it is better then write one code 1000 times…

---

<div class="post-metadata">

**Author:** ![llvdl](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/llvdl/32/78_2.png) [@llvdl](https://discourse.slimframework.com/u/llvdl)\
**Post date:** [October 8, 2016, 7:29am UTC](https://discourse.slimframework.com/t/response-with-json-scheme/776/7 "2016-10-08T07:29:45Z")

</div>

You can also create a service for providing the json response and inject it into your controller, or get it from the service container (depending on how you set up your actions and controllers):

```php
// A provider for returning the responses
class SJsonResponseProvider
{
    public function withOk($response, $data, $message = null)
    {
        return $response->withJson(['status' => 'success', 'data' => $data, 'message' => $message]);
    }
    
    public function withError($response, $message, $statusCode)
    {
        return $response->withJson(['status' => 'error', 'data' => $data, 'message' => $message], $statusCode);
    }
}

// add the service to the service container
$app = new \Slim\App([
    // define service for the provider
    'json_provider' => function() { return new SJsonResponseProvider(); }
]);

$app->get('/', function($request, $response) {
    // return OK 
    return $this->json_provider->withOk($response, ['token'=>'1234']);
    // return error
    return $this->json_provider->withError($response, 'Lecturer not exist', 404);
});

```

Or your can use traits:

```php
trait SJsonResponseProvidable
{
    private function withJsonOk($response, $data, $message = null)
    {
        return $response->withJson(['status' => 'success', 'data' => $data, 'message' => $message]);
    }

    private function withJsonError($response, $message, $statusCode)
    {
        return $response->withJson(['status' => 'error', 'data' => $data, 'message' => $message], $statusCode);
    }
}

class MyAction
{
    // add the trait to this action
    use SJsonResponseProvidable;

    public function __invoke($request, $response)
    {
        // return OK
        return $this->withJsonOk($response, ['token' => '1234']);
        // return erorr
        return $this->withJsonError($response, 'Lecturer not exist', 404);
    }
}

```

---

<div class="post-metadata">

**Author:** ![AndersonDev](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/andersondev/32/50_2.png) [@AndersonDev](https://discourse.slimframework.com/u/AndersonDev)\
**Post date:** [October 8, 2016, 7:54pm UTC](https://discourse.slimframework.com/t/response-with-json-scheme/776/9 "2016-10-08T19:54:50Z")

</div>

May I get default Response? Why you modify response:

```auto
$headers = new Headers(['Content-Type' => 'text/html; charset=UTF-8']);
$response = new MyResponse(200, $headers);
return $response->withProtocolVersion($slimContainer->get('settings')['httpVersion']);

```

and what is in `$encodingOptions`?

Thanks!
