JsonResponse

class JsonResponse extends Response

Response represents an HTTP response in JSON format.

Note that this class does not force the returned JSON content to be an object. It is however recommended that you do return an object as it protects yourself against XSSI and JSON-JavaScript Hijacking.

Constants

HTTP_CONTINUE = 100;

HTTP_SWITCHING_PROTOCOLS = 101;

HTTP_PROCESSING = 102; // RFC2518

HTTP_OK = 200;

HTTP_CREATED = 201;

HTTP_ACCEPTED = 202;

HTTP_NON_AUTHORITATIVE_INFORMATION = 203;

HTTP_NO_CONTENT = 204;

HTTP_RESET_CONTENT = 205;

HTTP_PARTIAL_CONTENT = 206;

HTTP_MULTI_STATUS = 207; // RFC4918

HTTP_ALREADY_REPORTED = 208; // RFC5842

HTTP_IM_USED = 226; // RFC3229

HTTP_MULTIPLE_CHOICES = 300;

HTTP_MOVED_PERMANENTLY = 301;

HTTP_FOUND = 302;

HTTP_SEE_OTHER = 303;

HTTP_NOT_MODIFIED = 304;

HTTP_USE_PROXY = 305;

HTTP_RESERVED = 306;

HTTP_TEMPORARY_REDIRECT = 307;

HTTP_PERMANENTLY_REDIRECT = 308; // RFC7238

HTTP_BAD_REQUEST = 400;

HTTP_UNAUTHORIZED = 401;

HTTP_PAYMENT_REQUIRED = 402;

HTTP_FORBIDDEN = 403;

HTTP_NOT_FOUND = 404;

HTTP_METHOD_NOT_ALLOWED = 405;

HTTP_NOT_ACCEPTABLE = 406;

HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;

HTTP_REQUEST_TIMEOUT = 408;

HTTP_CONFLICT = 409;

HTTP_GONE = 410;

HTTP_LENGTH_REQUIRED = 411;

HTTP_PRECONDITION_FAILED = 412;

HTTP_REQUEST_ENTITY_TOO_LARGE = 413;

HTTP_REQUEST_URI_TOO_LONG = 414;

HTTP_UNSUPPORTED_MEDIA_TYPE = 415;

HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;

HTTP_EXPECTATION_FAILED = 417;

HTTP_I_AM_A_TEAPOT = 418; // RFC2324

HTTP_MISDIRECTED_REQUEST = 421; // RFC7540

HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918

HTTP_LOCKED = 423; // RFC4918

HTTP_FAILED_DEPENDENCY = 424; // RFC4918

HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425; // RFC2817

HTTP_UPGRADE_REQUIRED = 426; // RFC2817

HTTP_PRECONDITION_REQUIRED = 428; // RFC6585

HTTP_TOO_MANY_REQUESTS = 429; // RFC6585

HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585

HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451;

HTTP_INTERNAL_SERVER_ERROR = 500;

HTTP_NOT_IMPLEMENTED = 501;

HTTP_BAD_GATEWAY = 502;

HTTP_SERVICE_UNAVAILABLE = 503;

HTTP_GATEWAY_TIMEOUT = 504;

HTTP_VERSION_NOT_SUPPORTED = 505;

HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295

HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918

HTTP_LOOP_DETECTED = 508; // RFC5842

HTTP_NOT_EXTENDED = 510; // RFC2774

HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585

DEFAULT_ENCODING_OPTIONS = 15;

Properties

ResponseHeaderBag $headers from Response
protected string $content from Response
protected string $version from Response
protected int $statusCode from Response
protected string $statusText from Response
protected string $charset from Response
static array $statusTexts Status codes translation table. from Response
protected $data
protected $callback
protected $encodingOptions

Methods

public __construct(mixed $data = null, $status = 200, array $headers = array(), bool $json = false) No description
public static Response create(mixed $data = null, int $status = 200, array $headers = array()) Factory method for chainability.
public string __toString() Returns the Response as an HTTP string. from Response
public __clone() Clones the current Response instance. from Response
public $this prepare(Request $request) Prepares the Response before it is sent to the client. from Response
public $this sendHeaders() Sends HTTP headers. from Response
public $this sendContent() Sends content for the current web response. from Response
public $this send() Sends HTTP headers and content. from Response
public $this setContent(mixed $content) Sets the response content. from Response
public string getContent() Gets the current response content. from Response
public $this setProtocolVersion($version) Sets the HTTP protocol version (1.0 or 1.1). from Response
public getProtocolVersion() Gets the HTTP protocol version. from Response
public $this setStatusCode($code, $text = null) Sets the response status code. from Response
public getStatusCode() Retrieves the status code for the current web response. from Response
public $this setCharset($charset) Sets the response charset. from Response
public getCharset() Retrieves the response charset. from Response
public isCacheable() Returns true if the response may safely be kept in a shared (surrogate) cache. from Response
public isFresh() Returns true if the response is "fresh". from Response
public isValidateable() Returns true if the response includes headers that can be used to validate the response with the origin server using a conditional GET request. from Response
public $this setPrivate() Marks the response as "private". from Response
public $this setPublic() Marks the response as "public". from Response
public $this setImmutable($immutable = true) Marks the response as "immutable". from Response
public isImmutable() Returns true if the response is marked as "immutable". from Response
public mustRevalidate() Returns true if the response must be revalidated by caches. from Response
public getDate() Returns the Date header as a DateTime instance. from Response
public $this setDate(DateTimeInterface $date) Sets the Date header. from Response
public getAge() Returns the age of the response in seconds. from Response
public $this expire() Marks the response stale by setting the Age header to be equal to the maximum age of the response. from Response
public getExpires() Returns the value of the Expires header as a DateTime instance. from Response
public $this setExpires(DateTimeInterface $date = null) Sets the Expires HTTP header with a DateTime instance. from Response
public getMaxAge() Returns the number of seconds after the time specified in the response's Date header when the response should no longer be considered fresh. from Response
public $this setMaxAge($value) Sets the number of seconds after which the response should no longer be considered fresh. from Response
public $this setSharedMaxAge($value) Sets the number of seconds after which the response should no longer be considered fresh by shared caches. from Response
public getTtl() Returns the response's time-to-live in seconds. from Response
public $this setTtl($seconds) Sets the response's time-to-live for shared caches in seconds. from Response
public $this setClientTtl($seconds) Sets the response's time-to-live for private/client caches in seconds. from Response
public getLastModified() Returns the Last-Modified HTTP header as a DateTime instance. from Response
public $this setLastModified(DateTimeInterface $date = null) Sets the Last-Modified HTTP header with a DateTime instance. from Response
public getEtag() Returns the literal value of the ETag HTTP header. from Response
public $this setEtag(string|null $etag = null, bool $weak = false) Sets the ETag value. from Response
public $this setCache($options) Sets the response's cache headers (validation and/or expiration). from Response
public $this setNotModified() Modifies the response so that it conforms to the rules defined for a 304 status code. from Response
public hasVary() Returns true if the response includes a Vary header. from Response
public getVary() Returns an array of header names given in the Vary header. from Response
public $this setVary(string|array $headers, bool $replace = true) Sets the Vary header. from Response
public bool isNotModified(Request $request) Determines if the Response validators (ETag, Last-Modified) match a conditional value specified in the Request. from Response
public isInvalid() Is response invalid? from Response
public isInformational() Is response informative? from Response
public isSuccessful() Is response successful? from Response
public isRedirection() Is the response a redirect? from Response
public isClientError() Is there a client error? from Response
public isServerError() Was there a server side error? from Response
public isOk() Is the response OK? from Response
public isForbidden() Is the response forbidden? from Response
public isNotFound() Is the response a not found error? from Response
public isRedirect($location = null) Is the response a redirect of some form? from Response
public isEmpty() Is the response empty? from Response
public static closeOutputBuffers($targetLevel, $flush) Cleans or flushes output buffers up to target level. from Response
protected ensureIEOverSSLCompatibility(Request $request) Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9. from Response
public static fromJsonString($data = null, $status = 200, $headers = array()) Make easier the creation of JsonResponse from raw json.
public $this setCallback(string|null $callback = null) Sets the JSONP callback.
public $this setJson(string $json) Sets a raw string containing a JSON document to be sent.
public $this setData(mixed $data = array()) Sets the data to be sent as JSON.
public int getEncodingOptions() Returns options used while encoding data to JSON.
public $this setEncodingOptions(int $encodingOptions) Sets options used while encoding data to JSON.
protected $this update() Updates the content and headers according to the JSON data and callback.

Details

at line 42

__construct()

public __construct(mixed $data = null, $status = 200, array $headers = array(), bool $json = false)

Parameters

mixed $data The response data
$status
array $headers
bool $json If the data is already a JSON string
at line 67

create()

public static Response create(mixed $data = null, int $status = 200, array $headers = array())

Factory method for chainability.

Example:

return JsonResponse::create($data, 200)
    ->setSharedMaxAge(300);

Parameters

mixed $data The json response data
int $status The response status code
array $headers An array of response headers

Return Value

Response
in Response at line 231

__toString()

public string __toString()

Returns the Response as an HTTP string.

The string representation of the Response is the same as the one that will be sent to the client only if the prepare() method has been called before.

Return Value

string The Response as an HTTP string

See also

prepare()
in Response at line 242

__clone()

public __clone()

Clones the current Response instance.

in Response at line 256

prepare()

public $this prepare(Request $request)

Prepares the Response before it is sent to the client.

This method tweaks the Response to ensure that it is compliant with RFC 2616. Most of the changes are based on the Request that is "associated" with this Response.

Parameters

Request $request

Return Value

$this
in Response at line 318

sendHeaders()

public $this sendHeaders()

Sends HTTP headers.

Return Value

$this
in Response at line 352

sendContent()

public $this sendContent()

Sends content for the current web response.

Return Value

$this
in Response at line 364

send()

public $this send()

Sends HTTP headers and content.

Return Value

$this
in Response at line 389

setContent()

public $this setContent(mixed $content)

Sets the response content.

Valid types are strings, numbers, null, and objects that implement a __toString() method.

Parameters

mixed $content Content that can be cast to string

Return Value

$this

Exceptions

UnexpectedValueException
in Response at line 405

getContent()

public string getContent()

Gets the current response content.

Return Value

string Content
in Response at line 417

setProtocolVersion()

public $this setProtocolVersion($version)

Sets the HTTP protocol version (1.0 or 1.1).

Parameters

$version

Return Value

$this
in Response at line 429

getProtocolVersion()

public getProtocolVersion()

Gets the HTTP protocol version.

in Response at line 446

setStatusCode()

public $this setStatusCode($code, $text = null)

Sets the response status code.

If the status text is null it will be automatically populated for the known status codes and left empty otherwise.

Parameters

$code
$text

Return Value

$this

Exceptions

InvalidArgumentException When the HTTP status code is not valid
in Response at line 475

getStatusCode()

public getStatusCode()

Retrieves the status code for the current web response.

in Response at line 487

setCharset()

public $this setCharset($charset)

Sets the response charset.

Parameters

$charset

Return Value

$this
in Response at line 499

getCharset()

public getCharset()

Retrieves the response charset.

in Response at line 521

isCacheable()

public isCacheable()

Returns true if the response may safely be kept in a shared (surrogate) cache.

Responses marked "private" with an explicit Cache-Control directive are considered uncacheable.

Responses with neither a freshness lifetime (Expires, max-age) nor cache validator (Last-Modified, ETag) are considered uncacheable because there is no way to tell when or how to remove them from the cache.

Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation, for example "status codes that are defined as cacheable by default [...] can be reused by a cache with heuristic expiration unless otherwise indicated" (https://tools.ietf.org/html/rfc7231#section-6.1)

in Response at line 543

isFresh()

public isFresh()

Returns true if the response is "fresh".

Fresh responses may be served from cache without any interaction with the origin. A response is considered fresh when it includes a Cache-Control/max-age indicator or Expires header and the calculated age is less than the freshness lifetime.

in Response at line 554

isValidateable()

public isValidateable()

Returns true if the response includes headers that can be used to validate the response with the origin server using a conditional GET request.

in Response at line 568

setPrivate()

public $this setPrivate()

Marks the response as "private".

It makes the response ineligible for serving other clients.

Return Value

$this
in Response at line 585

setPublic()

public $this setPublic()

Marks the response as "public".

It makes the response eligible for serving other clients.

Return Value

$this
in Response at line 600

setImmutable()

public $this setImmutable($immutable = true)

Marks the response as "immutable".

Parameters

$immutable

Return Value

$this
in Response at line 616

isImmutable()

public isImmutable()

Returns true if the response is marked as "immutable".

in Response at line 631

mustRevalidate()

public mustRevalidate()

Returns true if the response must be revalidated by caches.

This method indicates that the response must not be served stale by a cache in any circumstance without first revalidating with the origin. When present, the TTL of the response should not be overridden to be greater than the value provided by the origin.

in Response at line 643

getDate()

public getDate()

Returns the Date header as a DateTime instance.

Exceptions

RuntimeException When the header is not parseable
in Response at line 655

setDate()

public $this setDate(DateTimeInterface $date)

Sets the Date header.

Parameters

DateTimeInterface $date

Return Value

$this
in Response at line 672

getAge()

public getAge()

Returns the age of the response in seconds.

in Response at line 686

expire()

public $this expire()

Marks the response stale by setting the Age header to be equal to the maximum age of the response.

Return Value

$this
in Response at line 700

getExpires()

public getExpires()

Returns the value of the Expires header as a DateTime instance.

in Response at line 719

setExpires()

public $this setExpires(DateTimeInterface $date = null)

Sets the Expires HTTP header with a DateTime instance.

Passing null as value will remove the header.

Parameters

DateTimeInterface $date

Return Value

$this
in Response at line 746

getMaxAge()

public getMaxAge()

Returns the number of seconds after the time specified in the response's Date header when the response should no longer be considered fresh.

First, it checks for a s-maxage directive, then a max-age directive, and then it falls back on an expires header. It returns null when no maximum age can be established.

in Response at line 772

setMaxAge()

public $this setMaxAge($value)

Sets the number of seconds after which the response should no longer be considered fresh.

This methods sets the Cache-Control max-age directive.

Parameters

$value

Return Value

$this
in Response at line 788

setSharedMaxAge()

public $this setSharedMaxAge($value)

Sets the number of seconds after which the response should no longer be considered fresh by shared caches.

This methods sets the Cache-Control s-maxage directive.

Parameters

$value

Return Value

$this
in Response at line 806

getTtl()

public getTtl()

Returns the response's time-to-live in seconds.

It returns null when no freshness information is present in the response.

When the responses TTL is <= 0, the response may not be served from cache without first revalidating with the origin.

in Response at line 822

setTtl()

public $this setTtl($seconds)

Sets the response's time-to-live for shared caches in seconds.

This method adjusts the Cache-Control/s-maxage directive.

Parameters

$seconds

Return Value

$this
in Response at line 838

setClientTtl()

public $this setClientTtl($seconds)

Sets the response's time-to-live for private/client caches in seconds.

This method adjusts the Cache-Control/max-age directive.

Parameters

$seconds

Return Value

$this
in Response at line 852

getLastModified()

public getLastModified()

Returns the Last-Modified HTTP header as a DateTime instance.

Exceptions

RuntimeException When the HTTP header is not parseable
in Response at line 866

setLastModified()

public $this setLastModified(DateTimeInterface $date = null)

Sets the Last-Modified HTTP header with a DateTime instance.

Passing null as value will remove the header.

Parameters

DateTimeInterface $date

Return Value

$this
in Response at line 889

getEtag()

public getEtag()

Returns the literal value of the ETag HTTP header.

in Response at line 904

setEtag()

public $this setEtag(string|null $etag = null, bool $weak = false)

Sets the ETag value.

Parameters

string|null $etag The ETag unique identifier or null to remove the header
bool $weak Whether you want a weak ETag or not

Return Value

$this
in Response at line 930

setCache()

public $this setCache($options)

Sets the response's cache headers (validation and/or expiration).

Available options are: etag, last_modified, max_age, s_maxage, private, public and immutable.

Parameters

$options

Return Value

$this

Exceptions

InvalidArgumentException
in Response at line 987

setNotModified()

public $this setNotModified()

Modifies the response so that it conforms to the rules defined for a 304 status code.

This sets the status, removes the body, and discards any headers that MUST NOT be included in 304 responses.

Return Value

$this

See also

http://tools.ietf.org/html/rfc2616#section-10.3.5
in Response at line 1005

hasVary()

public hasVary()

Returns true if the response includes a Vary header.

in Response at line 1015

getVary()

public getVary()

Returns an array of header names given in the Vary header.

in Response at line 1039

setVary()

public $this setVary(string|array $headers, bool $replace = true)

Sets the Vary header.

Parameters

string|array $headers
bool $replace Whether to replace the actual value or not (true by default)

Return Value

$this
in Response at line 1057

isNotModified()

public bool isNotModified(Request $request)

Determines if the Response validators (ETag, Last-Modified) match a conditional value specified in the Request.

If the Response is not modified, it sets the status code to 304 and removes the actual content by calling the setNotModified() method.

Parameters

Request $request

Return Value

bool true if the Response validators match the Request, false otherwise
in Response at line 1089

isInvalid()

public isInvalid()

Is response invalid?

See also

http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
in Response at line 1099

isInformational()

public isInformational()

Is response informative?

in Response at line 1109

isSuccessful()

public isSuccessful()

Is response successful?

in Response at line 1119

isRedirection()

public isRedirection()

Is the response a redirect?

in Response at line 1129

isClientError()

public isClientError()

Is there a client error?

in Response at line 1139

isServerError()

public isServerError()

Was there a server side error?

in Response at line 1149

isOk()

public isOk()

Is the response OK?

in Response at line 1159

isForbidden()

public isForbidden()

Is the response forbidden?

in Response at line 1169

isNotFound()

public isNotFound()

Is the response a not found error?

in Response at line 1179

isRedirect()

public isRedirect($location = null)

Is the response a redirect of some form?

Parameters

$location
in Response at line 1189

isEmpty()

public isEmpty()

Is the response empty?

in Response at line 1201

closeOutputBuffers()

public static closeOutputBuffers($targetLevel, $flush)

Cleans or flushes output buffers up to target level.

Resulting level can be greater than target level if a non-removable buffer has been encountered.

Parameters

$targetLevel
$flush
in Response at line 1223

ensureIEOverSSLCompatibility()

protected ensureIEOverSSLCompatibility(Request $request)

Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9.

Parameters

Request $request

See also

http://support.microsoft.com/kb/323308
at line 75

fromJsonString()

public static fromJsonString($data = null, $status = 200, $headers = array())

Make easier the creation of JsonResponse from raw json.

Parameters

$data
$status
$headers
at line 89

setCallback()

public $this setCallback(string|null $callback = null)

Sets the JSONP callback.

Parameters

string|null $callback The JSONP callback or null to use none

Return Value

$this

Exceptions

InvalidArgumentException When the callback name is not valid
at line 124

setJson()

public $this setJson(string $json)

Sets a raw string containing a JSON document to be sent.

Parameters

string $json

Return Value

$this

Exceptions

InvalidArgumentException
at line 140

setData()

public $this setData(mixed $data = array())

Sets the data to be sent as JSON.

Parameters

mixed $data

Return Value

$this

Exceptions

InvalidArgumentException
at line 163

getEncodingOptions()

public int getEncodingOptions()

Returns options used while encoding data to JSON.

Return Value

int
at line 175

setEncodingOptions()

public $this setEncodingOptions(int $encodingOptions)

Sets options used while encoding data to JSON.

Parameters

int $encodingOptions

Return Value

$this
at line 187

update()

protected $this update()

Updates the content and headers according to the JSON data and callback.

Return Value

$this

Source code

<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace App\Khan\Component\HttpFoundation;

/**
 * Response represents an HTTP response in JSON format.
 *
 * Note that this class does not force the returned JSON content to be an
 * object. It is however recommended that you do return an object as it
 * protects yourself against XSSI and JSON-JavaScript Hijacking.
 *
 * @see https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside
 *
 * @author Igor Wiedler <igor@wiedler.ch>
 */
class JsonResponse extends Response
{
    protected $data;
    protected $callback;

    // Encode <, >, ', &, and " characters in the JSON, making it also safe to be embedded into HTML.
    // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT
    const DEFAULT_ENCODING_OPTIONS = 15;

    protected $encodingOptions = self::DEFAULT_ENCODING_OPTIONS;

    /**
     * @param mixed $data    The response data
     * @param int   $status  The response status code
     * @param array $headers An array of response headers
     * @param bool  $json    If the data is already a JSON string
     */
    public function __construct($data = null, int $status = 200, array $headers = array(), bool $json = false)
    {
        parent::__construct('', $status, $headers);

        if (null === $data) {
            $data = new \ArrayObject();
        }

        $json ? $this->setJson($data) : $this->setData($data);
    }

    /**
     * Factory method for chainability.
     *
     * Example:
     *
     *     return JsonResponse::create($data, 200)
     *         ->setSharedMaxAge(300);
     *
     * @param mixed $data    The json response data
     * @param int   $status  The response status code
     * @param array $headers An array of response headers
     *
     * @return static
     */
    public static function create($data = null, $status = 200, $headers = array())
    {
        return new static($data, $status, $headers);
    }

    /**
     * Make easier the creation of JsonResponse from raw json.
     */
    public static function fromJsonString($data = null, $status = 200, $headers = array())
    {
        return new static($data, $status, $headers, true);
    }

    /**
     * Sets the JSONP callback.
     *
     * @param string|null $callback The JSONP callback or null to use none
     *
     * @return $this
     *
     * @throws \InvalidArgumentException When the callback name is not valid
     */
    public function setCallback($callback = null)
    {
        if (null !== $callback) {
            // partially taken from http://www.geekality.net/2011/08/03/valid-javascript-identifier/
            // partially taken from https://github.com/willdurand/JsonpCallbackValidator
            //      JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details.
            //      (c) William Durand <william.durand1@gmail.com>
            $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\.|[^"\\\])*"|\'(?:\\\.|[^\'\\\])*\'|\d+)\])*?$/u';
            $reserved = array(
                'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while',
                'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super',  'const', 'export',
                'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false',
            );
            $parts = explode('.', $callback);
            foreach ($parts as $part) {
                if (!preg_match($pattern, $part) || in_array($part, $reserved, true)) {
                    throw new \InvalidArgumentException('The callback name is not valid.');
                }
            }
        }

        $this->callback = $callback;

        return $this->update();
    }

    /**
     * Sets a raw string containing a JSON document to be sent.
     *
     * @param string $json
     *
     * @return $this
     *
     * @throws \InvalidArgumentException
     */
    public function setJson($json)
    {
        $this->data = $json;

        return $this->update();
    }

    /**
     * Sets the data to be sent as JSON.
     *
     * @param mixed $data
     *
     * @return $this
     *
     * @throws \InvalidArgumentException
     */
    public function setData($data = array())
    {
        try {
            $data = json_encode($data, $this->encodingOptions);
        } catch (\Exception $e) {
            if ('Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) {
                throw $e->getPrevious() ?: $e;
            }
            throw $e;
        }

        if (JSON_ERROR_NONE !== json_last_error()) {
            throw new \InvalidArgumentException(json_last_error_msg());
        }

        return $this->setJson($data);
    }

    /**
     * Returns options used while encoding data to JSON.
     *
     * @return int
     */
    public function getEncodingOptions()
    {
        return $this->encodingOptions;
    }

    /**
     * Sets options used while encoding data to JSON.
     *
     * @param int $encodingOptions
     *
     * @return $this
     */
    public function setEncodingOptions($encodingOptions)
    {
        $this->encodingOptions = (int) $encodingOptions;

        return $this->setData(json_decode($this->data));
    }

    /**
     * Updates the content and headers according to the JSON data and callback.
     *
     * @return $this
     */
    protected function update()
    {
        if (null !== $this->callback) {
            // Not using application/javascript for compatibility reasons with older browsers.
            $this->headers->set('Content-Type', 'text/javascript');

            return $this->setContent(sprintf('/**/%s(%s);', $this->callback, $this->data));
        }

        // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback)
        // in order to not overwrite a custom definition.
        if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) {
            $this->headers->set('Content-Type', 'application/json');
        }

        return $this->setContent($this->data);
    }
}