Я пытаюсь вернуть объект JSON из одной из моих REST-моделей, что-то вроде этого:
{
"settings": {
"set1" : 2,
"set2" : "key1"
},
"extra": {
"e1'" : {
"e2'": true
}
}
}
Однако то, что кажется на первый взгляд тривиальным, не так просто реализовать. Проблема в том, что я не уверен, какой тип возврата должен быть в интерфейсе и модели.
<?php
namespace AppFactory\Core\Api;
/**
* @api
*/
interface SettingsInterface
{
/**
* @return object
*/
public function get();
}
Класс объекта вернется
{
"message": "Class object does not exist",
при вызове API. Доступные типы примитивов int, number и array для меня не подойдут. Я не хочу создавать класс для каждого возвращаемого сложного типа. Как я могу это сделать?
Спасибо.
magento2
webapi
magento2-api
Yehia A.Salam
источник
источник
Ответы:
Я предполагаю, что
AppFactory\Core\Api\SettingInterface::get()
это конечная точка REST. В этом случае в комментариях phpdoc вы должны определить, что это будет возвращать. Обработчик Magento REST примет это значение и обработает его, чтобы удалить все ненужные данные. То, что осталось, будет закодировано в JSON, поэтому в javascript вы можете получить его как уже правильный JS-хэш, а не как json-кодированную строку.Хитрость этих конечных точек заключается в том, что вам нужно очень точно определить, что вы вернете. Magento не сможет обрабатывать что-то такое общее, как «массив», где вы будете устанавливать все, что вам нравится.
В вашем случае, чтобы не пытаться играть с массивом строк, будет проще создать интерфейс, который будет возвращать ваша конечная точка.
Теперь, когда вы возвращаете экземпляр объекта, реализующего этот интерфейс, Magento будет читать его phpdocs и обрабатывать их возвращаемые значения. Теперь создайте файл
AppFactory\Core\Api\Data\SettingsInterface
следующим образомТеперь, когда вы создадите реальный класс, который будет реализовывать эти 2 метода get, и вы вернете его,
AppFactory\Core\Api\SettingsInterface::get()
magento вернет что-то вродеЕсли вы хотите другой уровень, вам нужно создать другой интерфейс, который сохранит
settings
структуру и добавит его в качестве возвращаемого значения дляAppFactory\Core\Api\Data\SettingsInterface::getSettings()
.Если вам нужно что-то, что будет динамичным, и вы не хотите или не можете подготовить этот интерфейс структуры, тогда вы можете попробовать установить json-закодированную строку и место
@return string
для любого из полей. Таким образом, однако, вы должны будете убедиться, что вручную расшифровали эту строку после получения ответа, так как тогда ваш ответ будет выглядеть так:и для того, чтобы использовать,
response.extra.test
вам придется сначала сделатьresponse.extra = JSON.parse(response.extra);
вручнуюисточник
AppFactory\Core\Api\DataSettingsInterface
. Если это работает, вам нужно только сделать первый уровень ответа.Я также столкнулся с этой проблемой, и в качестве альтернативы предложенному @Zefiryn решению я обошел ее, заключив возвращаемые данные в массив (или два). Пожалуйста, рассмотрите пример ниже.
Благодаря тому, что Magento 2 допускает массивы смешанного содержимого в качестве возвращаемых значений, более сложные структуры данных могут быть встроены в другие массивы. В приведенном выше примере получен следующий ответ JSON (усеченный для удобства чтения).
Включение его в один слой удаляет ключи массива, а без включения его в какой-либо массив приводит к ошибке.
Понятно, что все это не идеально, но этот подход позволяет мне в определенной степени контролировать согласованность возвращаемой структуры данных (ожидаемой структуры и типов данных). Если вы также управляете написанием клиентской библиотеки, может быть реализован перехватчик для удаления внешнего массива перед его возвратом в приложение.
источник
Для Magento 2.3.1, если вам нужно обойти сериализацию массива, вы можете проверить этот файл, чтобы обновить логику ядра. Я думаю, что это хорошая отправная точка. Но, сделав это, вы наверняка нарушите совместимость Soap.
Более того, в Magento 2.1.X у вас нет этой проблемы, если вы указали в качестве типа возврата anyType.
Ссылка на Github: https://github.com/magento/magento2/blob/2.3-develop/lib/internal/Magento/Framework/Reflection/TypeCaster.php
Ссылка на изменение изменений: https://github.com/magento/magento2/commit/6ba399cdaea5babb373a35e88131a8cbd041b0de#diff-53855cf24455a74e11a998ac1a871bb8
продавец / Magento / рамки / Отражение / TypeCaster.php: 42
И заменить на:
источник
Я знаю, что этот вопрос довольно старый, но есть одно довольно простое решение для этого:
Вам нужно либо заменить Json-Renderer,
Magento\Framework\Webapi\Rest\Response\Renderer\Json
либо написать плагин для него.Вот небольшой пример плагина:
В вашей
di.xml
В вашем новом плагин-классе
Namespace\Module\Plugin\Webapi\RestResponse\JsonPlugin
Что здесь происходит:
Конечно, вы также можете написать свой собственный Renderer, который, например, обрабатывает массив.
источник
Я столкнулся с той же проблемой, и мне потребовалось некоторое время, чтобы понять проблему.
Magento делает что-то странное в этом выходном процессоре службы web api, который находится в Magento \ Framework \ Webapi \ ServiceOutputProcessor. В этом классе есть метод с именем convertValue (); что является причиной для скобок [].
Лучшее решение для меня, чтобы решить эту проблему, было создать плагин вокруг, чтобы преодолеть это условие if в convertValue (); метод, в котором они проверяют, является ли $ data массивом, и делают с ним странные вещи.
Вот мой пример кода плагина: я думаю, что каждый знает, как создать базовый модуль Magento 2, поэтому я публикую здесь только код самого плагина.
Создать папку плагинов
Создайте класс Vendor \ ModuleName \ Plugin \ ServiceOutputProcessorPlugin.php
Это должно решить проблему вывода массива JSON в веб-API
Надеюсь это поможет
источник