Why does the Yii2 rest controller respond in XML format?

I am currently using the following initialization code for my api module

public function init() { parent::init(); Yii::$app->response->format = Response::FORMAT_JSON; } 

My api returns an XML response in the following example.

 public function actionTest() { $items = ['one', 'two', 'three' => ['a', 'b', 'c']]; return $items; } 

This is the answer:

 <response> <item>one</item> <item>two</item> <three> <item>a</item> <item>b</item> <item>c</item> </three> </response> 

The only way I can get it to work is to add this line to every controller behavior. I read the documentation that says that I can initialize this in a module class, so I do not need to do this in every controller. I do not know why this gives XML. Also , if the only way to add it to my behavior, I need to write code to handle the name, code, status, type, previous and code, or Yii to provide yii \ rest \ Controller and yii \ rest \ ActiveController that automatically handle this. Obviously, they are automatically displayed when an error occurs.

 {"name":"Not Found" "message":"Page not found.", "code":0, "status":404 "type":"yii\\web\\NotFoundHttpException" "previous":{"name":"Invalid Route","message":"Unable to resolve the request: api/home/", "code":0,"type":"yii\\base\\InvalidRouteException" } } 
+6
source share
3 answers

In Yii2 applications, the default response type is XML (and I think it is the default for REST too). During an HTTP connection, both parties declare what types of data can send and / or receive. If this information is not passed to the server, the data type is sent by default (even if you indicated that it should be JSON in your application) to ensure proper communication. If you want to receive JSON data, you must add the Accept: application/json header to your request. And probably you do not need to specify it in php code, because Yii2 should subtract it from the request headers.

You can find more explanations of how this works here .

+4
source

After three painful days, I found a solution. It is sometimes quite difficult to explain this problem when you come from a whole world of JSON ExpressJS and NodeJS. Logically, what Yii2 does is fine, on the other hand, the 90% RESTful API expects the output to be in JSON, so you obviously don't want to set request headers every time you call the API call.

By default, browsers add request headers as "Application / XML", so you see XML instead of JSON on the screen.

Yii2 content negotiation when receiving headers as an application / xml formats your output in XML. If you make the same request using CURL or PostMan with headers like "Application / JSON", you will get the desired result.

If you want to override this behavior, just add the following function to your controller and enable the following: -

use yii \ web \ Response; use yii \ helpers \ ArrayHelper;

 public function behaviors() { return ArrayHelper::merge(parent::behaviors(), [ [ 'class' => 'yii\filters\ContentNegotiator', 'only' => ['view', 'index'], // in a controller // if in a module, use the following IDs for user actions // 'only' => ['user/view', 'user/index'] 'formats' => [ 'application/json' => Response::FORMAT_JSON, ], 'languages' => [ 'en', 'de', ], ], ]); } 
+4
source

I am testing my code and it works great

my controller:

 <?php namespace backend\controllers; use yii\rest\Controller; use yii; use yii\web\Response; class TestController extends Controller{ public function init() { parent::init(); Yii::$app->response->format = Response::FORMAT_JSON; } public function actionTest(){ $items = ['one', 'two', 'three' => ['a', 'b', 'c']]; return $items; } } 

Output:

 {"0":"one","1":"two","three":["a","b","c"]} 

check your namespace or submit your code!

+3
source

All Articles