Estoy tratando de devolver un objeto JSON de uno de mis modelos REST, algo como esto:
{
"settings": {
"set1" : 2,
"set2" : "key1"
},
"extra": {
"e1'" : {
"e2'": true
}
}
}
Sin embargo, lo que parece trivial no es tan fácil de implementar. El problema es que no estoy seguro de cuál debería ser el tipo de retorno en la interfaz y el modelo.
<?php
namespace AppFactory\Core\Api;
/**
* @api
*/
interface SettingsInterface
{
/**
* @return object
*/
public function get();
}
La clase de objeto devolverá
{
"message": "Class object does not exist",
al llamar a la API. Los tipos primitivos disponibles int, number y array no funcionarán para mí. No quiero crear una clase para cada tipo complejo que también regresa. ¿Cómo puedo hacer esto?
Gracias.
magento2
webapi
magento2-api
Yehia A.Salam
fuente
fuente
Respuestas:
Supongo que
AppFactory\Core\Api\SettingInterface::get()
es un punto final REST. En ese caso, en los comentarios de phpdoc debe definir qué devolverá esto. El manejador REST de Magento tomará ese valor y lo procesará para eliminar todos los datos que sean innecesarios. Lo que queda se codificará en JSON, por lo que en javascript puede recuperarlo como un hash JS adecuado y no una cadena codificada con json.El truco sobre esos puntos finales es que debe definir con mucha precisión qué devolverá. Magento no podrá procesar algo tan general como "matriz" donde establecerá lo que quiera.
En su caso, para no intentar jugar con una variedad de cadenas, será más fácil crear una interfaz que devolverá su punto final.
Ahora, cuando devuelve una instancia de un objeto que implementa esa interfaz, Magento leerá sus phpdocs y procesará sus valores de retorno. Ahora cree un archivo de la
AppFactory\Core\Api\Data\SettingsInterface
siguiente maneraAhora, cuando crea una clase real que implementará esos 2 métodos get y la devolverá,
AppFactory\Core\Api\SettingsInterface::get()
entonces magento devolverá algo comoSi desea otro nivel, debe crear otra interfaz que mantenga la
settings
estructura y la agregue como valor de retornoAppFactory\Core\Api\Data\SettingsInterface::getSettings()
.Si necesita tener algo que sea dinámico y no desea o no puede preparar esta interfaz de estructura, puede intentar configurar una cadena codificada con json y colocarla
@return string
en cualquiera de los campos. De esta manera, sin embargo, deberá asegurarse de decodificar manualmente esa cadena después de recibir la respuesta, ya que su respuesta se verá así:y para usarlo
response.extra.test
primeroresponse.extra = JSON.parse(response.extra);
deberá hacerlo manualmentefuente
AppFactory\Core\Api\DataSettingsInterface
. Si esto funciona, solo necesita hacer el primer nivel de la respuesta.También me he enfrentado a este problema y, como alternativa a la solución propuesta por @Zefiryn, he solucionado el problema al encerrar los datos de retorno en una matriz (o dos). Por favor considere el siguiente ejemplo.
Debido a cómo Magento 2 permite matrices de contenido mixto como valores de retorno, se pueden incrustar estructuras de datos más complejas dentro de otras matrices. La muestra anterior produce la siguiente respuesta JSON (truncada para facilitar la lectura).
Al encerrarlo en una sola capa se eliminan las claves de la matriz, y sin encerrarlo en ninguna matriz se produce un error.
Es comprensible que nada de esto sea ideal, pero este enfoque me permite controlar la consistencia en la estructura de datos devuelta en cierto grado (la estructura y los tipos de datos esperados). Si también tiene el control de escribir una biblioteca del lado del cliente, se puede implementar un interceptor para eliminar la matriz externa antes de devolverla a la aplicación.
fuente
Para Magento 2.3.1, si necesita omitir la serialización de la matriz, puede verificar este archivo para actualizar la lógica central. Creo que es un buen punto de entrada. Pero al hacer esto, seguramente romperá la compatibilidad de Soap.
Además, en Magento 2.1.X, no tiene este problema si coloca anyType como tipo de retorno.
Referencia de Github: https://github.com/magento/magento2/blob/2.3-develop/lib/internal/Magento/Framework/Reflection/TypeCaster.php
Confirmar referencia de cambio: https://github.com/magento/magento2/commit/6ba399cdaea5babb373a35e88131a8cbd041b0de#diff-53855cf24455a74e11a998ac1a871bb8
vendor / magento / framework / Reflection / TypeCaster.php: 42
Y reemplazar por:
fuente
Sé que esta pregunta es bastante antigua, pero hay una solución bastante simple para esto:
Es necesario reemplazar el Json-Renderer
Magento\Framework\Webapi\Rest\Response\Renderer\Json
o escribir un complemento para él.Aquí un pequeño ejemplo de un complemento:
En tus
di.xml
En tu nueva clase de plugin
Namespace\Module\Plugin\Webapi\RestResponse\JsonPlugin
Qué pasa aquí:
Por supuesto, también puede escribir su propio Renderer, que procesa una matriz, por ejemplo.
fuente
Me enfrenté al mismo problema y me tomó un tiempo resolverlo.
Magento hace algo extraño en el procesador de salida del servicio de API web que se encuentra en Magento \ Framework \ Webapi \ ServiceOutputProcessor. En esta clase hay un método llamado convertValue (); cuál es la razón de las llaves [].
La mejor solución para resolver el problema fue crear un complemento alrededor para superar esto si la condición en el convertValue (); método en el que comprueban si $ data es una matriz y hacen cosas raras con él.
Aquí está mi código de ejemplo del complemento: creo que todos saben cómo crear un módulo básico de Magento 2, por lo que solo publico el código del complemento aquí.
Crear una carpeta de complementos
Cree una clase Vendor \ ModuleName \ Plugin \ ServiceOutputProcessorPlugin.php
Esto debería resolver el problema de salida de array json en la API web
Espero que esto ayude
fuente