0

I'm returning JSON via an endpoint in Magento 2 this bit of JSON looks like the following:

    $new_json = [
        'component_1' => '[{....}]', 
        'component_2' => '[{...}]'
    ];
    return $new_json;

The endpoint works, but it returns the following:

0: "...."
1: "...."

Now I can pass the JSON into [ ] to return the following, but this isn't what I want:

[0]:
component_1: "...."
component_2: "...."

My issue is I need to return the JSON with key and value, not 0 and 1 nor a sub value e.g. [0]

Is there a setting for the endpoint to stop it encoding the JSON like this? Or is there something I need to do to return it in the way that I want?

Thanks.

  • try this return [$new_json] ; – Shafeel Sha Aug 23 at 14:09
3
+50

Problem Summary: You have a PHP Array and you want to return it as a JSON Object. When you return your PHP Array, it gets converted to a JSON Array, which does not support non-sequential keys. So your keys get ignored and you end up with a sequential array of your values.

Solution Summary: You need to return a PHP Object in order to have a JSON Object in your response.

Solution Example

Please check following example that returns a sample Components object.

/Api/Data/ComponentsInterface.php

<?php
namespace Company\Components\Api\Data;

/**
 * Interface ComponentsInterface
 */
interface ComponentsInterface
{
    /**
     * Get component 1
     *
     * @return string
     */
    public function getComponent1();

    /**
     * Get component 2
     *
     * @return string
     */
    public function getComponent2();
}

/Api/ComponentsManagamentInterface.php

<?php
namespace Company\Components\Api;

/**
 * Components Management interface
 */
interface ComponentsManagementInterface
{
    /**
     * @return \Company\Components\Api\Data\ComponentsInterface
     */
    public function getComponents();
}

/etc/webapi.xml

<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
    <route url="/V1/components" method="GET">
        <service class="Company\Components\Api\ComponentsManagementInterface" method="getComponents"/>
    </route>
</routes>

/Model/Components.php

<?php
namespace Company\Components\Model;

/**
 * Components model
 */
class Components extends \Magento\Framework\DataObject implements \Company\Component\Api\Data\ComponentsInterface
{
    /**
     * @inheritDoc
     */
    public function getComponent1() 
    {
        return $this->getData('component1');
    }

    /**
     * @inheritDoc
     */
    public function getComponent2()
    {
        return $this->getData('component2');
    }
}

/Model/ComponentsManagement.php

<?php
namespace Company\Components\Model;

/**
 * Components Management
 */
class ComponentsManagement implements \Company\Components\Api\ComponentsManagementInterface
{
    /**
    * @var \Company\Components\Api\Data\ComponentsInterfaceFactory
    */
    protected $_componentsFactory;

    /**
    * ComponentsManagement constructor.
    * @param \Company\Components\Api\Data\ComponentsInterfaceFactory $_componentsFactory
    */
    public function __construct(\Company\Components\Api\Data\ComponentsInterfaceFactory $_componentsFactory)
    {
        $this->_componentsFactory = $_componentsFactory;
    }

    /**
     * @inheritDoc
     */
    public function getComponents()
    {
        $components = $this->_componentsFactory->create();
        $components->setData([
            'component1' => '[{....}]',
            'component2' => '[{....}]'
            ]);
        return $components;
    }
}

/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="Company\Components\Api\Data\ComponentsInterface"
                type="Company\Components\Model\Components"/>
    <preference for="Company\Components\Api\ComponentsManagementInterface"
                type="Company\Components\Model\ComponentsManagement"/>
</config>

With above example, when you GET http://magento/rest/V1/components it will return following JSON Object:

{"component_1":"[{....}]","component_2":"[{....}]"}
  • This answer is absolutely fantastic. How would i go about modifying the 'component1' to be 'something-1' ? – andy jones Aug 24 at 13:27
  • @andyjones You may use underscore, but dashes are not allowed in such naming, please review Magento\Framework\Reflection\DataObjectProcessor::buildOutputDataArray and Magento\Framework\Reflection\FieldNamer::getFieldNameForMethodName methods it will make more sense. – muhammedv Aug 24 at 17:04
  • 1
    According to the getFieldNameForMethodName method, the response would use underscores. component_1 and component_2 instead of component1 and component2 – Andres Rojas Orozco Aug 26 at 20:45
0

Try this code in your controller.

protected $resultJsonFactory;

public function __construct(
    \Magento\Framework\App\Action\Context $context,
    \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
){   
    parent::__construct($context);
    $this->resultJsonFactory   = $resultJsonFactory;
}

public function execute()
{
    $result = $this->resultJsonFactory->create();
    $data = array('component_1' => '[{....}]', 'component_2' => '[{...}]');
    $result->setData($data);
    return $result;
}
  • 1
    The question is based on WebAPI, not a controller. – muhammedv Aug 23 at 22:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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