cakan
cakan

Reputation: 2117

Return an empty array as object with JsonModel

I am making a REST method with Zend Framework 2 which returns JSON response. For that I'm using the following code:

return new JsonModel($result);

In some cases, result is an empty array and JsonModel outputs that as []. Is it possible to force JsonModel to display empty array as an object, i.e. {}?

In PHP, you can do the following:

echo json_encode(array(), JSON_FORCE_OBJECT);

Is there a similar option to JSON_FORCE_OBJECT that I could use with JsonModel in zf2? I have tried all combinations of the following, but with no luck.

return new JsonModel(array(), JSON_FORCE_OBJECT);

Upvotes: 0

Views: 950

Answers (2)

irvinstone
irvinstone

Reputation: 623

Use the response object:

    $result   = array();
    $data     = json_encode($result, JSON_FORCE_OBJECT);
    $response = $this->getResponse();
    return $response->setContent($data);

Upvotes: 0

rkeet
rkeet

Reputation: 3468

If you'd've followed the code, you would've found that it's not possible with the provided JsonModel by Zend.


Zend\View\Model\JsonModel has this serialize function:

public function serialize()
{
    $variables = $this->getVariables();
    if ($variables instanceof Traversable) {
        $variables = ArrayUtils::iteratorToArray($variables);
    }

    $options = [
        'prettyPrint' => $this->getOption('prettyPrint'),
    ];

    if (null !== $this->jsonpCallback) {
        return $this->jsonpCallback.'('.Json::encode($variables, false, $options).');';
    }
    return Json::encode($variables, false, $options);
}

The Json::encode leads to Zend\Json\Json, and the encode() function

public static function encode($valueToEncode, $cycleCheck = false, array $options = [])
{
    if (is_object($valueToEncode)) {
        if (method_exists($valueToEncode, 'toJson')) {
            return $valueToEncode->toJson();
        }

        if (method_exists($valueToEncode, 'toArray')) {
            return static::encode($valueToEncode->toArray(), $cycleCheck, $options);
        }
    }

    // Pre-process and replace javascript expressions with placeholders
    $javascriptExpressions = new SplQueue();
    if (isset($options['enableJsonExprFinder'])
       && $options['enableJsonExprFinder'] == true
    ) {
        $valueToEncode = static::recursiveJsonExprFinder($valueToEncode, $javascriptExpressions);
    }

    // Encoding
    $prettyPrint = (isset($options['prettyPrint']) && ($options['prettyPrint'] === true));
    $encodedResult = self::encodeValue($valueToEncode, $cycleCheck, $options, $prettyPrint);

    // Post-process to revert back any Zend\Json\Expr instances.
    $encodedResult = self::injectJavascriptExpressions($encodedResult, $javascriptExpressions);

    return $encodedResult;
}

As you can see, the encoding function has been commented for you, so we need the self::encodeValue function, clicking through on that leads to:

private static function encodeValue($valueToEncode, $cycleCheck, array $options, $prettyPrint)
{
    if (function_exists('json_encode') && static::$useBuiltinEncoderDecoder !== true) {
        return self::encodeViaPhpBuiltIn($valueToEncode, $prettyPrint);
    }

    return self::encodeViaEncoder($valueToEncode, $cycleCheck, $options, $prettyPrint);
}

Judging by your question, you have json_encode built-in function available, so we step into the if() and execute the self::encodeViaPhpBuiltIn() function:

private static function encodeViaPhpBuiltIn($valueToEncode, $prettyPrint = false)
{
    if (! function_exists('json_encode') || static::$useBuiltinEncoderDecoder === true) {
        return false;
    }

    $encodeOptions = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP;

    if ($prettyPrint) {
        $encodeOptions |= JSON_PRETTY_PRINT;
    }

    return json_encode($valueToEncode, $encodeOptions);
}

This has the same check again, but finally ends up with:

return json_encode($valueToEncode, $encodeOptions);

The options are set hardcoded in the function, with the exception of the optional "JSON_PRETTY_PRINT" option.


The answer you're looking for is: no, it's not possible.


However, you could, technically, write your own replacement for JsonModel, make sure that your own model is used by the JsonViewStrategy and use it then... Just an option.

Upvotes: 3

Related Questions