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.

1
  • try this return [$new_json] ; Commented Aug 23, 2019 at 14:09

2 Answers 2

4
+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":"[{....}]"}
4
  • This answer is absolutely fantastic. How would i go about modifying the 'component1' to be 'something-1' ?
    – andy jones
    Commented Aug 24, 2019 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
    Commented Aug 24, 2019 at 17:04
  • 1
    According to the getFieldNameForMethodName method, the response would use underscores. component_1 and component_2 instead of component1 and component2 Commented Aug 26, 2019 at 20:45
  • What does the ComponentsInterfaceFactory file look like?
    – Simon Mo
    Commented Dec 27, 2019 at 0:16
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
  • 1
    The question is based on WebAPI, not a controller.
    – muhammedv
    Commented Aug 23, 2019 at 22:52

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.