1

I have a problem with the json output when sending a request to the API.

I receive data in this format:

"{\n    \"name\": \"John\",\n    \"age\": 30,\n    \"car\": null,\n   \"address\": {\n        \"street\": \"123 Main St\",\n        \"city\": \"Anytown\",\n        \"zip\": \"12345\"\n    }\n}"

I need the data in this format:

{
    "name": "John",
    "age": 30,
    "car": null,
    "address": {
        { "street": "123 Main St",
        "city": "Anytown",
        "zip": "12345"
    }
}

Am I correct in understanding that this is because I am using such an interface on my side?

namespace Dev\RestApi\Api;

interface TestInterface
{
    /**
    *
    * @return string
    */
    public function testMethod();
}

My Model:

namespace Dev\RestApi\Model;

use Dev\RestApi\Api\TestInterface;

class TestModel implements TestInterface
{
    public function testMethod()
    {

        $data = [
            'name' => 'John',
            'age' => 30,
            'car' => null,
            'some' => null,
            'address' => [
                'street' => '123 Main St',
                'city' => 'Anytown',
                'zip' => '12345'
            ]
        ];

        $jsonResponse = json_encode($data, JSON_PRETTY_PRINT);

        return $jsonResponse;
    }
}
1
  • You could remove JSON_PRETTY_PRINT if you don’t want the formatting in the result? Commented Oct 18, 2023 at 16:16

2 Answers 2

1

If you want to return the result as a JSON object via a rest API call, you must use data objects with appropriate interfaces. Your method (testMethod()) should return, say, CustomerDataInterface, whereas CustomerDataInterface should have a getAddress method that returns AddressDataInterface. The Rest API has some limitations, and one of them is the inability to return simple arrays.

Example:

app/code/Dev/RestApi/Api/Data/AddressInterface.php

namespace Dev\RestApi\Api\Data;

interface AddressInterface
{
    /**
     * Get street.
     *
     * @return string|null
     */
    public function getStreet(): ?string;

    /**
     * Get city.
     *
     * @return string|null
     */
    public function getCity(): ?string;

    /**
     * Get zip code.
     *
     * @return string|null
     */
    public function getZip(): ?string;
}

app/code/Dev/RestApi/Model/Address.php

namespace Dev\RestApi\Model;

use Dev\RestApi\Api\Data\AddressInterface;

class Address implements AddressInterface
{
    /**
     * @var string|null
     */
    private $street;

    /**
     * @var string|null
     */
    private $city;

    /**
     * @var string|null
     */
    private $zip;

    /**
     * Set street.
     *
     * @param string|null $street
     * @return AddressInterface
     */
    public function setStreet(?string $street): AddressInterface
    {
        $this->street = $street;
        return $this;
    }

    /**
     * Set city.
     *
     * @param string|null $city
     * @return AddressInterface
     */
    public function setCity(?string $city): AddressInterface
    {
        $this->city = $city;
        return $this;
    }

    /**
     * Set zip code.
     *
     * @param string|null $zip
     * @return AddressInterface
     */
    public function setZip(?string $zip): AddressInterface
    {
        $this->zip = $zip;
        return $this;
    }

    /**
     * Get street.
     *
     * @return string|null
     */
    public function getStreet(): ?string
    {
        return $this->street;
    }

    /**
     * Get city.
     *
     * @return string|null
     */
    public function getCity(): ?string
    {
        return $this->city;
    }

    /**
     * Get zip code.
     *
     * @return string|null
     */
    public function getZip(): ?string
    {
        return $this->zip;
    }
}

app/code/Dev/RestApi/Api/Data/MainDataInterface.php

namespace Dev\RestApi\Api\Data;

interface MainDataInterface
{
    /**
     * Get name.
     *
     * @return string|null
     */
    public function getName(): ?string;

    /**
     * Get age.
     *
     * @return int|null
     */
    public function getAge(): ?int;

    /**
     * Get car.
     *
     * @return string|null
     */
    public function getCar(): ?string;

    /**
     * Get some.
     *
     * @return string|null
     */
    public function getSome(): ?string;

    /**
     * Get address.
     *
     * @return \Dev\RestApi\Api\Data\AddressInterface
     */
    public function getAddress(): AddressInterface;
}

app/code/Dev/RestApi/Model/MainData.php

namespace Dev\RestApi\Model;

use Dev\RestApi\Api\Data\MainDataInterface;
use Dev\RestApi\Api\Data\AddressInterface;

class MainData implements MainDataInterface
{
    /**
     * @var string|null
     */
    private $name;

    /**
     * @var int|null
     */
    private $age;

    /**
     * @var string|null
     */
    private $car;

    /**
     * @var string|null
     */
    private $some;

    /**
     * @var AddressInterface
     */
    private $address;

    public function __construct(AddressInterface $address)
    {
        $this->address = $address;
    }

    /**
     * Set name.
     *
     * @param string|null $name
     * @return MainDataInterface
     */
    public function setName(?string $name): MainDataInterface
    {
        $this->name = $name;
        return $this;
    }

    /**
     * Set age.
     *
     * @param int|null $age
     * @return MainDataInterface
     */
    public function setAge(?int $age): MainDataInterface
    {
        $this->age = $age;
        return $this;
    }

    /**
     * Set car.
     *
     * @param string|null $car
     * @return MainDataInterface
     */
    public function setCar(?string $car): MainDataInterface
    {
        $this->car = $car;
        return $this;
    }

    /**
     * Set some.
     *
     * @param string|null $some
     * @return MainDataInterface
     */
    public function setSome(?string $some): MainDataInterface
    {
        $this->some = $some;
        return $this;
    }

    /**
     * Get name.
     *
     * @return string|null
     */
    public function getName(): ?string
    {
        return $this->name;
    }

    /**
     * Get age.
     *
     * @return int|null
     */
    public function getAge(): ?int
    {
        return $this->age;
    }

    /**
     * Get car.
     *
     * @return string|null
     */
    public function getCar(): ?string
    {
        return $this->car;
    }

    /**
     * Get some.
     *
     * @return string|null
     */
    public function getSome(): ?string
    {
        return $this->some;
    }

    /**
     * Get address.
     *
     * @return \Dev\RestApi\Api\Data\AddressInterface
     */
    public function getAddress(): AddressInterface
    {
        return $this->address;
    }
}

Update preferences in the di.xml:

app/code/Dev/RestApi/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Dev\RestApi\Api\Data\MainDataInterface" type="Dev\RestApi\Model\MainData" />
    <preference for="Dev\RestApi\Api\Data\AddressInterface" type="Dev\RestApi\Model\Address" />
</config>

Update your main interface and model:

app/code/Dev/RestApi/Api/TestInterface.php

namespace Dev\RestApi\Api;

use Dev\RestApi\Api\Data\MainDataInterface;

interface TestInterface
{
    /**
     * @return MainDataInterface
     */
    public function testMethod(): MainDataInterface;
}

app/code/Dev/RestApi/Model/TestModel.php

namespace Dev\RestApi\Model;

use Dev\RestApi\Api\TestInterface;
use Dev\RestApi\Api\Data\MainDataInterface;
use Dev\RestApi\Model\MainData; // Assuming you have MainData class

class TestModel implements TestInterface
{
    public function testMethod(): MainDataInterface
    {
        $mainData = new MainData();
        
        $mainData
            ->setName('John')
            ->setAge(30)
            ->setCar(null)
            ->setSome(null);

        $address = new Address();
        $address
            ->setStreet('123 Main St')
            ->setCity('Anytown')
            ->setZip('12345');

        $mainData->setAddress($address);

        return $mainData;
    }
}

PS: This is just a quickly generated sample code, you should update it to suit your needs and best practices!

1
  • 1
    Thanks for the help! Your example works!
    – User
    Commented Oct 24, 2023 at 13:22
0

If you want to get JSON foramt, you can use Magento\Framework\Controller\Result\JsonFactory

In TestModel, inject JsonFactory into the class and set the $data into JsonFactory. So that:

namespace Dev\RestApi\Model;

use Dev\RestApi\Api\TestInterface;
use Magento\Framework\Controller\Result\JsonFactory;

class TestModel implements TestInterface
{
    protected JsonFactory $jsonFactory;

    public function __construct(
        JsonFactory $jsonFactory
    ){
        $this->jsonFactory = $jsonFactory;
    }

    public function testMethod()
    {

        $data = [
            'name' => 'John',
            'age' => 30,
            'car' => null,
            'some' => null,
            'address' => [
                'street' => '123 Main St',
                'city' => 'Anytown',
                'zip' => '12345'
            ]
        ];

        $jsonResponse = $this->jsonFactory->create();
        $jsonResponse->setData($data);

        return $jsonResponse;
    }
}
2
  • Thank you for your response! Unfortunately, I got an empty array... If I output the $data variable, I get a JSON array: [ "John", 30, null, null, { "street": "123 Main St", "city": "Anytown", "zip": "12345" } ] If $jsonResponse: [] Perhaps you know what could be causing the problem?
    – User
    Commented Oct 19, 2023 at 12:08
  • If this is a REST api call, then you can return $data directly.
    – PY Yick
    Commented Oct 19, 2023 at 14:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.