I'm trying to return a JSON object from one of my REST Models, something like this:
{
"settings": {
"set1" : 2,
"set2" : "key1"
},
"extra": {
"e1'" : {
"e2'": true
}
}
}
However, what seemingly looks trivial, is not that easy to implement. The problem is I'm not sure what the return type should be in the interface and model.
<?php
namespace AppFactory\Core\Api;
/**
* @api
*/
interface SettingsInterface
{
/**
* @return object
*/
public function get();
}
The object class will return
{
"message": "Class object does not exist",
when calling the API. The primitive types available int, number, and array won't work for me. I don't want to create a class for each complex type is returning as well. How can I do this?
Thanks.
Best Answer
I am assuming that
AppFactory\Core\Api\SettingInterface::get()
is a REST endpoint. In that case in phpdoc comments you need to define what this will return. Magento REST handler will take that value and process it to remove all data that are unnecessary. What's left will be encoded into JSON so in javascript you can retrieve it as already proper JS hash and not json-encoded string.The trick about those endpoint is that you need to define very precisely what will you return. Magento will not be able to process something as general as "array" where you will set whatever you like.
In your case, in order not to try playing with array of strings, it will be easier to create an interface that your endpoint will return.
Now when you return an instance of an object implementing that interface Magento will read its phpdocs and will process their return values. Now create a file in
AppFactory\Core\Api\Data\SettingsInterface
as followsNow when you create actual class that will implement those 2 get methods and you will return it in
AppFactory\Core\Api\SettingsInterface::get()
then magento will return something likeIf you want another level you need to create another interface which will keep
settings
structure and add it as a return value forAppFactory\Core\Api\Data\SettingsInterface::getSettings()
.If you need to have something that will be dynamic and you do not want or can't prepare this structure interface then you can try setting json-encoded string and place
@return string
for any of the fields. This way however you will have to make sure to manually decode that string after receiving the response as then your response will look like this:and in order to use
response.extra.test
you will have to first doresponse.extra = JSON.parse(response.extra);
manually