Тонкие выходы JSON

Я использую фреймворк Slim с PHP для создания RESTful API для своего приложения. Однако я предполагал, что у фреймворка будет какой-то способ создания более простых выходных данных JSON, а не просто exit($jsonEncodedVariable);.

Я что-то упустил во фреймворке или мне нужно использовать json_encode()... exit($json)... для каждого метода?

Все данные берутся из моей базы данных MySQL, а затем помещаются в массив JSON в зависимости от того, какой запрос REST был вызван.

Например, если бы было запрошено /api/posts/all, я бы exit() создал массив JSON всех сообщений, каждое из которых имеет значение для собственного ключа, "value" : key.

Мой вопрос в том, есть ли простой способ, используя тонкий фреймворк, для exit() кода JSON вместо того, чтобы выходить из него как обычный текст?


person max_    schedule 24.07.2011    source источник
comment
Пожалуйста, отредактируйте свой вопрос с дополнительной информацией о вашей проблеме. Трудно получить то, что вы просите от вашего нынешнего.   -  person genesis    schedule 24.07.2011
comment
отредактировано. Вам нужно больше информации?   -  person max_    schedule 24.07.2011


Ответы (16)


header("Content-Type: application/json");
echo json_encode($result);
exit;

Подсказка: Использование Slim PHP Framework для Разработка REST API

person hakre    schedule 24.07.2011
comment
ИМО, это должно было быть выбрано в качестве ответа, потому что оно устанавливает правильный заголовок типа контента как часть ответа. - person hashchange; 08.09.2011
comment
Я не согласен, ответ Orangewrap задает тип контента через объект ответа, а не через функцию заголовка. Любой метод действителен. А зачем выходить? - person Brady Emerson; 02.12.2013
comment
Только потому, что вы можете, это не должно означать, что вам нужно. Как всегда, есть много способов добиться того, о чем спрашивают, поэтому я не скажу, что мой ответ здесь более или менее правильный, чем другой ответ. - person hakre; 02.12.2013
comment
Я не согласен, потому что ответ показывает естественные параметры Framework. Я ответил примером использования правильных параметров для Slim - person jeff_drumgod; 21.09.2016
comment
Этот ответ написан в 2011 году, сейчас все немного по-другому. Не рекомендуется возвращать результаты echo, вместо этого обратные вызовы маршрута должны возвращать объект ответа PSR. Кроме того, даже тогда, почему exit? - person Nima; 02.08.2017
comment
@Nima: Вы уже назвали время ответа, и я думаю, что это главная его часть. Однако, как вы спрашиваете: я считаю важным (в духе слим-фреймворка) привести самый короткий пример. Но даже тогда выходом, скорее всего, будет запах, и return должно хватить (если вообще понадобится). Однако STDOUT — не такая уж плохая концепция для HTTP-ответов. Я лишь немного знаком со Слимом, но могу себе представить, что Слим прекрасно с этим справляется. Я не пытаюсь сказать, что ResponseObject даст больше возможностей. См. также предыдущий комментарий для дополнительных опций. - person hakre; 02.08.2017
comment
Просто подумал, что было бы неплохо указать другим посетителям официальную документацию Slim здесь slimframework .com/docs/objects/response.html#returning-json . Потому что я вижу много вопросов о SO, спрашивающих, как этого добиться, что означает, что эти вопросы и их ответы, вероятно, по-прежнему привлекают много внимания, и, поскольку это принятый ответ, некоторые люди могут полагаться на него, и это нормально, потому что это работает , но, как я уже сказал, Слим предлагает метод, облегчающий эту задачу. - person Nima; 03.08.2017
comment
Хорошая ссылка, однако она не показывает правильный ответ, если вы хотите передать уже закодированную строку JSON;) - person hakre; 03.08.2017

Почему бы просто не использовать объект ответа Слима? (также... зачем выходить?)

$dataAry = // Some data array

$response = $app->response();
$response['Content-Type'] = 'application/json';
$response['X-Powered-By'] = 'Potato Energy';
$response->status(200);
// etc.

$response->body(json_encode($dataAry));
// Or echo json_encode($dataAry)

Позвольте мне в предисловии сказать, что я все еще считаю себя нубом, поэтому, если я делаю ошибки, поправьте меня, чтобы я мог учиться. Но я играл с похожей проблемой/вопросом и подумал, что могу добавить 2 цента и заархивировать еще немного обсуждения по этому вопросу. Чем больше информации о Slim on Stack, тем лучше.

По сути, я играл с тем же и заметил, что вы используете exit; Сначала я использовал выход еще и потому, что эхо включало кучу HTML и искажало то, что возвращалось в мой вызов AJAX. Когда я использовал выход, он аккуратно вырезал HTML, но затем объект ответа Slim не менял заголовки ответа, как я определил (см. код выше).

Я понял, что это не то, как Слим был разработан для работы. Используйте эхо, а не выход. ПРИМЕЧАНИЕ. Тонкий документ:

Всякий раз, когда вы используете содержимое echo() из обратного вызова маршрута, содержимое, переданное echo(), захватывается > в буфере вывода и позже добавляется к телу ответа, прежде чем ответ HTTP будет > возвращен клиенту.

Это удобно, но я не смог повторить. То, что я испортил, было большей проблемой. Отделение содержания от поведения. Если вы похожи на меня, вы настраиваете одностраничное приложение, где этот код в основном находится на index.php. Есть исходный html, который мне нужно было загрузить, поэтому я включил его на эту страницу. Что мне нужно было сделать, так это создать более чистое разделение. Моя маршрутизация была правильно настроена, и поэтому, когда люди ПОЛУЧАЮТ '/', Slim_Views (см. Develop Rel.) возвращает мне обработанный шаблон html и js. Великолепно!

Теперь у меня есть все инструменты Слима, и мой код намного чище, раздельнее, управляемее и более совместим с протоколами http. Думаю, для этого и нужны фреймворки. :-)

ПРИМЕЧАНИЕ. Я не говорю, что все это произошло с вашей стороны, но я подумал, что вопрос и ваша установка кажутся очень похожими. Это может помочь другому новичку, который идет по тому же пути.

ОБНОВЛЕНИЕ: как упоминает @alttag, этот ответ устаревает (Slim 2)

Для Slim3 см. ответ ниже или см. эту страницу в документации

person jmk2142    schedule 31.01.2012
comment
Хм. Я нашел ваш ответ здесь и хотел попробовать. выход просто выглядел обманом... однако мне пришлось выйти. Я отправляю свой междоменный запрос и чтобы заставить ajax обработать запрос, который мне пришлось выйти () после моего эха json_data - person Jake; 08.03.2012
comment
Я действительно использовал решение, как вы сказали, и оно работает очень хорошо. Несколько советов: если вам нужно использовать переменную $app внутри лямбда-функции, следует добавить ее в область действия, например: function() use($app) {}; или вы можете получить экземпляр с помощью \Slim\Slim::getInstance()! - person alexserver; 11.02.2013
comment
О боже, спасибо! Я не знаю, почему header(content-type: application/json); у меня не сработало, но ваше решение работает отлично! Здорово ! :D - person TDK; 16.01.2014
comment
альтернативно, $app->response->headers->set('Content-Type', 'application/json'); - person Jack James; 11.07.2014
comment
Это лучший ответ. - person chrisbjr; 06.11.2014
comment
Это хороший ответ Slim2. Для Slim3 см. ответ ниже или см. эту страницу в документации. - person alttag; 08.11.2018
comment
Upvote - я очень-очень давно не использовал SLIM. Я включу эту ссылку как редактирование в старый ответ. - person jmk2142; 09.11.2018

Используя Slim 3, я использую этот формат:

<?php

$app = new \Slim\App();

$app->get('/{id}', function ($request, $response, $args) {
    $id = $request->getAttribute('id');

    return $response->withJSON(
        ['id' => $id],
        200,
        JSON_UNESCAPED_UNICODE
    );
});

По запросу "/123" результат JSON с:

{
  id: "123"
}

Подробнее читайте здесь.

[ОБНОВЛЕНИЕ] Добавлены второй и третий параметры в withJSON. Во-вторых, это код состояния HTTP, а в-третьих, это параметры кодирования Json (лучше всего подходит для специальных символов и других, например: правильно печатать «ã»)

person jeff_drumgod    schedule 28.02.2016
comment
Нужно ли возвращать этот объект? Или достаточно вернуть void (нет возврата), а сделать все остальное, как показывает наш пример? - person hakre; 02.08.2017
comment
Я не знаю, понял ли я ваш комментарий @hakre, но для Slim\Http\Response::withJson() ожидается 1 аргумент. Вы можете отправить строку, например foo, и тело браузера напечатает foo с заголовком content-type:application/json. Но обычно вы используете этот тип контента с JSON, потому что мой возврат — это массив. - person jeff_drumgod; 03.08.2017
comment
@hakre В Slim3 необходимо вернуть измененный $response, потому что объект ответа неизменяем. Ваши изменения не будут внесены, если вы не вернете обновленный ответ. - person alttag; 08.11.2018

вы можете расширить slim с помощью функции вывода, вывод которой зависит от запроса REST:

class mySlim extends Slim\Slim {
    function outputArray($data) {
        switch($this->request->headers->get('Accept')) {
            case 'application/json':
            default:
                $this->response->headers->set('Content-Type', 'application/json');
                echo json_encode($data);        
        }       
    } 
}

$app = new mySlim();

и используйте его так:

$app->get('/test/', function() use ($app) {
    $data = array(1,2,3,4);
    $app->outputArray($data);
});
person d3nnis    schedule 23.08.2013

Поскольку все усложнили свои ответы функциями и классами, я добавлю этот упрощенный ответ. \Slim\Http\Response может сделать это за вас следующим образом:

$app = new \Slim\Slim();

$app->get('/something', function () use ($app) {
    $response = $app->response();
    $response['Content-Type'] = 'application/json';
    $response->status(200);
    $response->body(json_encode(['data' => []]));
});

$app->run();

Поскольку вы, скорее всего, возвращаете только данные JSON, может быть хорошей идеей создать соответствующее промежуточное программное обеспечение, см. http://www.sitepoint.com/best-practices-rest-api-scratch-introduction/.

person Andreas Bergström    schedule 13.04.2015

Я думаю, что Slim также предоставляет объект промежуточного программного обеспечения, который делает это автоматически, поэтому пользователям этого фреймворка не нужно писать json_decode и кодировать при каждом запросе, он называется объектом Slim_Middleware_ContentType.

$app->response()->('application/json');
$app->add(new Slim_Middleware_ContentType());

он делает расшифровку для вас. декодирование работает отлично. Но для кодирования последний пост великолепен.

Спасибо, Дхарани.

person Dharani Dharan A    schedule 21.06.2012
comment
Обратите внимание, что это изменилось, и теперь это: $app->add(New \Slim\Middleware\ContentTypes()); - person ehime; 26.06.2013

Я чувствую твою боль. Я хотел сделать повторно используемую функцию, поэтому я сделал вспомогательный файл и включил это:

function toJSON($app, $content) {
    $response = $app->response;
    $response['Content-Type'] = 'application/json';
    $response->body( json_encode($content) );
};

И тогда я использовал это так:

$app->get('/v1/users/:id', function($id) use ($app)
{
    //instantiate SMM data model
    $model = new user_model($site);

    //get all docs, or one, depending on if query contains a page ID
    $doc = $model->get(array());

    //if the object contains main -- we don't need the outer data.
    toJSON($app, $doc);
});

Редактировать: я думаю, было бы очень хорошо, если бы уже были встроены такие функции в объект ответа для популярных типов пантомимы.

person Kristian    schedule 06.08.2013

почему не $response->write(json_encode($dataAry)); вместо echo json_encode($dataAry); ?

person k33g_org    schedule 01.06.2012
comment
Вам нужно поместить json в заголовок - person Pini Cheyni; 01.03.2016

Мое исправление заключалось в добавлении «выход»; в конце распечатки json моему серверу разработки было все равно, но мой живой сервер не запускал событие окончания json. Мне не нужно было добавлять заголовки или использовать json_encode.

person pikknz    schedule 04.10.2012

Используйте Slim JSON API https://coderwall.com/p/otcphg/create-a-json-restfull-api-using-slim-framework. С ним вы можете обрабатывать вывод JSON.

person Юрий Шпакович    schedule 27.04.2015

[ДО]: Content-Type text/html; кодировка = UTF-8

Не работает с SOAPUI JSON :(

$this->get('get_all', function ($req, $res, $args) {
    $um = new UserModel();

    return $res
       ->withHeader('Content-Type', 'application/json')
       ->getBody()
       ->write(
        json_encode(
            $um->get_all()
        )
    );
});

[ПОСЛЕ]: Content-Type application/json;charset=utf-8

Работа с SOAPUI JSON;)

$this->get('get_all', function ($req, $res, $args) {
    $um = new UserModel();

    return $res
        ->withHeader('Content-type', 'application/json;charset=utf-8')
        ->withJson($um->get_all());
person user3104260    schedule 13.06.2016

Вы можете использовать в slim3 пользовательский метод объекта Slim's Response withJson($data, $status, $encodingOptions)

$app->get('/hello/{name}', function ($request, $response, $args) {
    $data['msg']='Hello '.$request->getAttribute('name');
    $newResponse = $response->withJson($data);
});

Подробнее читайте здесь.

person Nanhe Kumar    schedule 22.07.2016

Вот как я это делаю в тонкой версии 2

$app->response->headers->set("Content-Type", 'application/json');
return $app->response->write(json_encode([
    'status' => true,
    'message' => 'Your message'
]));
person Sajjad Ashraf    schedule 08.04.2018

Я использую https://github.com/entomb/slim-json-api для мой API написан на Slim 2 для включения JSON-ответа. Код инициализации выглядит примерно так:

function APIRequests () {
    $app = \Slim\Slim::getInstance();
    $app->view(new \JsonApiView());
    $app->add(new \JsonApiMiddleware());
}

$app->group('/api', 'APIRequests', function () use ($app) {
    $app->get('/areas/:id', function ($id) use ($app) {
       $app->render(200, Area::find($id));
    });
});

Мне очень нравится уровень абстракции с использованием промежуточного программного обеспечения и группировки маршрутов, что позволяет легко применять разные типы ответов к разным областям приложения.

person emccracken    schedule 20.07.2015

заголовок ("Тип контента: приложение/json"); эхо json_encode ($ данные);

person Sumit Shinde    schedule 02.02.2017

person    schedule
comment
хотя я и рекомендую что-то в этом роде, мне бы очень хотелось, чтобы вы поместили это в контекст типичного тонкого запроса. - person Kristian; 06.08.2013