Вернуть пустой массив как объект с JsonModel - PullRequest
0 голосов
/ 14 декабря 2018

Я делаю метод REST с Zend Framework 2, который возвращает ответ JSON.Для этого я использую следующий код:

return new JsonModel($result);

В некоторых случаях результатом является пустой массив, и JsonModel выводит его как [].Можно ли заставить JsonModel отображать пустой массив в виде объекта, например {}?

В PHP вы можете сделать следующее:

echo json_encode(array(), JSON_FORCE_OBJECT);

Есть ли подобная опция для JSON_FORCE_OBJECT что я мог бы использовать с JsonModel в zf2?Я перепробовал все следующие комбинации, но безуспешно.

return new JsonModel(array(), JSON_FORCE_OBJECT);

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Использовать объект ответа:

    $result   = array();
    $data     = json_encode($result, JSON_FORCE_OBJECT);
    $response = $this->getResponse();
    return $response->setContent($data);
0 голосов
/ 18 декабря 2018

Если бы вы следовали коду, вы бы обнаружили, что не возможно с предоставленным Zend JsonModel.


Zend\View\Model\JsonModel имеет эту функцию сериализации:

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);
}

Json::encode ведет к Zend\Json\Json, а функция encode()

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;
}

Как видите, функция кодирования была закомментирована для вас, поэтому нам нужна функция self::encodeValue, нажатие на которую приводит к:

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);
}

Судя по вашему вопросу, у вас есть json_encodeдоступна встроенная функция, поэтому мы добавляем в if() и выполняем функцию self::encodeViaPhpBuiltIn():

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);
}

Это снова выполняет ту же проверку, но в итоге заканчивается:

return json_encode($valueToEncode, $encodeOptions);

Параметры жестко заданы в функции, за исключением дополнительной опции "JSON_PRETTY_PRINT".


Ответ, который вы ищете: нет , это невозможно.


Однако , вы могли бы , технически, напишите свою собственную замену для JsonModel, убедитесь, что ваша собственная модель используется JsonViewStrategyи использовать его тогда ... Просто вариант.

...