Estou tentando retornar um objeto JSON de um dos meus modelos REST, algo como isto:
{
"settings": {
"set1" : 2,
"set2" : "key1"
},
"extra": {
"e1'" : {
"e2'": true
}
}
}
No entanto, o que parece trivial, não é tão fácil de implementar. O problema é que não tenho certeza de qual deve ser o tipo de retorno na interface e no modelo.
<?php
namespace AppFactory\Core\Api;
/**
* @api
*/
interface SettingsInterface
{
/**
* @return object
*/
public function get();
}
A classe de objeto retornará
{
"message": "Class object does not exist",
ao chamar a API. Os tipos primitivos disponíveis int, number e array não funcionarão para mim. Eu não quero criar uma classe para cada tipo complexo que está retornando também. Como posso fazer isso?
Obrigado.
magento2
webapi
magento2-api
Yehia A.Salam
fonte
fonte
Respostas:
Estou assumindo que
AppFactory\Core\Api\SettingInterface::get()
é um ponto de extremidade REST. Nesse caso, nos comentários do phpdoc, você precisa definir o que isso retornará. O manipulador REST Magento pega esse valor e o processa para remover todos os dados desnecessários. O que resta será codificado em JSON, portanto, em javascript, você pode recuperá-lo como hash JS já adequado e não como uma string codificada por json.O truque sobre esses pontos de extremidade é que você precisa definir com muita precisão o que retornará. O Magento não será capaz de processar algo tão geral como "array", onde você definirá o que quiser.
No seu caso, para não tentar jogar com uma série de cadeias, será mais fácil criar uma interface que seu endpoint retornará.
Agora, quando você retornar uma instância de um objeto implementando essa interface, o Magento lerá seus phpdocs e processará seus valores de retorno. Agora crie um arquivo da
AppFactory\Core\Api\Data\SettingsInterface
seguinte maneiraAgora, quando você cria uma classe real que implementará esses 2 métodos get e você a retornará, o
AppFactory\Core\Api\SettingsInterface::get()
magento retornará algo comoSe você quiser outro nível, precisará criar outra interface que mantenha a
settings
estrutura e a adicione como valor de retornoAppFactory\Core\Api\Data\SettingsInterface::getSettings()
.Se você precisar de algo que seja dinâmico e não desejar ou não puder preparar essa interface de estrutura, tente definir a string codificada por json e o local
@return string
para qualquer um dos campos. Dessa forma, porém, você precisará decodificar manualmente essa sequência após receber a resposta, pois sua resposta será semelhante a esta:e para usar
response.extra.test
você terá que primeiro fazerresponse.extra = JSON.parse(response.extra);
manualmentefonte
AppFactory\Core\Api\DataSettingsInterface
. Se isso funcionar, você precisa apenas executar o primeiro nível da resposta.Também enfrentei esse problema e, como alternativa à solução proposta por Zefiryn, resolvi-o colocando os dados de retorno em uma matriz (ou duas). Por favor, considere o exemplo abaixo.
Devido à forma como o Magento 2 permite matrizes de conteúdo misto como valores de retorno, estruturas de dados mais complexas podem ser incorporadas dentro de outras matrizes. A amostra acima produz a seguinte resposta JSON (truncada para facilitar a leitura).
Colocá-lo em uma única camada remove as chaves da matriz e, sem incluí-la em nenhuma matriz, resulta em um erro.
Compreensivelmente, nada disso é ideal, mas essa abordagem me permite controlar a consistência na estrutura de dados retornada até um certo grau (a estrutura e os tipos de dados esperados). Se você também estiver no controle da gravação de uma biblioteca do lado do cliente, um interceptador poderá ser implementado para remover a matriz externa antes de devolvê-la ao aplicativo.
fonte
Para o Magento 2.3.1, se você precisar ignorar a serialização do array, poderá verificar este arquivo para atualizar a lógica principal. Eu acho que é um bom ponto de entrada. Mas, ao fazer isso, você quebrará a compatibilidade do Soap com certeza.
Além disso, no Magento 2.1.X, você não tem esse problema se colocar anyType como tipo de retorno.
Referência do Github: https://github.com/magento/magento2/blob/2.3-develop/lib/internal/Magento/Framework/Reflection/TypeCaster.php
Confirme a referência de alteração: https://github.com/magento/magento2/commit/6ba399cdaea5babb373a35e88131a8cbd041b0de#diff-53855cf24455a74e11a998ac1a871bb8
fornecedor / magento / framework / Reflexão / TypeCaster.php: 42
E substitua por:
fonte
Eu sei que essa pergunta é bastante antiga, mas há uma solução bastante simples para isso:
Você precisa substituir o Json-Renderer
Magento\Framework\Webapi\Rest\Response\Renderer\Json
ou escrever um plug-in para ele.Aqui está um pequeno exemplo de um plugin:
Na tua
di.xml
Na sua nova classe de plug-ins
Namespace\Module\Plugin\Webapi\RestResponse\JsonPlugin
O que acontece aqui:
Claro que você também pode escrever seu próprio Renderer, que processa uma matriz, por exemplo.
fonte
Enfrentei o mesmo problema e demorei um pouco para descobrir o problema.
O Magento faz algo estranho no processador de saída de serviço de API da Web, localizado em Magento \ Framework \ Webapi \ ServiceOutputProcessor Nesta classe, existe um método chamado convertValue (); qual é o motivo dos chavetas [].
A melhor solução para resolver o problema foi criar um plugin around para superar essa condição if no convertValue (); método em que eles verificam se $ data é uma matriz e fazem coisas estranhas com ela.
Aqui está o meu exemplo de código do plug-in: Eu acho que todo mundo sabe como criar um módulo básico do Magento 2, então eu só publico o código do próprio plug-in aqui.
Crie uma pasta Plugin
Crie uma classe Vendor \ ModuleName \ Plugin \ ServiceOutputProcessorPlugin.php
Isso deve resolver o problema de saída do json da matriz na API da Web
Espero que isto ajude
fonte