Ich versuche, ein JSON-Objekt von einem meiner REST-Modelle zurückzugeben.
{
"settings": {
"set1" : 2,
"set2" : "key1"
},
"extra": {
"e1'" : {
"e2'": true
}
}
}
Was jedoch scheinbar trivial aussieht, ist nicht so einfach zu implementieren. Das Problem ist, dass ich nicht sicher bin, wie der Rückgabetyp in der Schnittstelle und im Modell aussehen soll.
<?php
namespace AppFactory\Core\Api;
/**
* @api
*/
interface SettingsInterface
{
/**
* @return object
*/
public function get();
}
Die Objektklasse wird zurückgegeben
{
"message": "Class object does not exist",
beim Aufruf der API. Die verfügbaren primitiven Typen int, number und array funktionieren bei mir nicht. Ich möchte nicht für jeden komplexen Typ eine Klasse erstellen, der ebenfalls zurückkehrt. Wie kann ich das machen?
Vielen Dank.
magento2
webapi
magento2-api
Yehia A. Salam
quelle
quelle
Antworten:
Ich gehe davon aus, dass dies
AppFactory\Core\Api\SettingInterface::get()
ein REST-Endpunkt ist. In diesem Fall müssen Sie in phpdoc-Kommentaren definieren, was dies zurückgeben soll. Der Magento REST-Handler nimmt diesen Wert und verarbeitet ihn, um alle unnötigen Daten zu entfernen. Was übrig bleibt, wird in JSON codiert, sodass Sie es in Javascript als bereits richtigen JS-Hash und nicht als json-codierten String abrufen können.Der Trick bei diesen Endpunkten besteht darin, dass Sie sehr genau definieren müssen, was Sie zurückgeben möchten. Magento ist nicht in der Lage, etwas so Allgemeines wie "Array" zu verarbeiten, in dem Sie festlegen können, was Sie möchten.
In Ihrem Fall ist es einfacher, eine Schnittstelle zu erstellen, die Ihr Endpunkt zurückgibt, um nicht mit einer Reihe von Zeichenfolgen zu spielen.
Wenn Sie nun eine Instanz eines Objekts zurückgeben, das diese Schnittstelle implementiert, liest Magento seine PHPDOCs und verarbeitet deren Rückgabewerte. Erstellen Sie nun eine Datei
AppFactory\Core\Api\Data\SettingsInterface
wie folgtWenn Sie nun eine tatsächliche Klasse erstellen, die diese
AppFactory\Core\Api\SettingsInterface::get()
beiden get-Methoden implementiert, und Sie sie zurückgeben, gibt magento so etwas wie zurückWenn Sie eine andere Ebene wünschen, müssen Sie eine andere Schnittstelle erstellen, die die
settings
Struktur beibehält und als Rückgabewert für hinzufügtAppFactory\Core\Api\Data\SettingsInterface::getSettings()
.Wenn Sie etwas benötigen, das dynamisch ist und Sie diese Strukturschnittstelle nicht vorbereiten möchten oder können, können Sie versuchen, eine json-codierte Zeichenfolge festzulegen und
@return string
für eines der Felder zu platzieren. Auf diese Weise müssen Sie jedoch sicherstellen, dass Sie diese Zeichenfolge nach Erhalt der Antwort manuell dekodieren, da Ihre Antwort dann folgendermaßen aussieht:und um zu verwenden, müssen
response.extra.test
Sie zuerstresponse.extra = JSON.parse(response.extra);
manuell tunquelle
AppFactory\Core\Api\DataSettingsInterface
. Wenn dies funktioniert, müssen Sie nur die erste Ebene der Antwort ausführen.Ich bin auch mit diesem Problem konfrontiert worden, und als Alternative zu der von @Zefiryn vorgeschlagenen Lösung habe ich es umgangen, indem ich die Rückgabedaten in ein Array (oder zwei) eingeschlossen habe. Bitte beachten Sie das folgende Beispiel.
Aufgrund der Tatsache, dass Magento 2 Arrays mit gemischtem Inhalt als Rückgabewerte zulässt, können komplexere Datenstrukturen in andere Arrays eingebettet werden. Das obige Beispiel liefert die folgende JSON-Antwort (aus Gründen der Lesbarkeit abgeschnitten).
Wenn Sie es in eine einzelne Ebene einschließen, werden die Schlüssel des Arrays entfernt, und ohne es in ein Array einzuschließen, führt dies zu einem Fehler.
Verständlicherweise ist nichts davon ideal, aber dieser Ansatz ermöglicht es mir, die Konsistenz in der zurückgegebenen Datenstruktur bis zu einem gewissen Grad (der erwarteten Datenstruktur und den erwarteten Datentypen) zu kontrollieren. Wenn Sie auch die Kontrolle über das Schreiben einer clientseitigen Bibliothek haben, kann ein Interceptor implementiert werden, um das äußere Array zu entfernen, bevor es an die Anwendung zurückgegeben wird.
quelle
Wenn Sie in Magento 2.3.1 die Array-Serialisierung umgehen müssen, können Sie diese Datei überprüfen, um die Kernlogik zu aktualisieren. Ich denke, es ist ein guter Einstiegspunkt. Auf diese Weise wird jedoch die Seifenkompatibilität mit Sicherheit beeinträchtigt.
Darüber hinaus tritt dieses Problem unter Magento 2.1.X nicht auf, wenn Sie anyType als Rückgabetyp angeben.
Github-Referenz: https://github.com/magento/magento2/blob/2.3-develop/lib/internal/Magento/Framework/Reflection/TypeCaster.php
Änderungsreferenz festschreiben: https://github.com/magento/magento2/commit/6ba399cdaea5babb373a35e88131a8cbd041b0de#diff-53855cf24455a74e11a998ac1a871bb8
Hersteller / Magento / Framework / Reflection / TypeCaster.php: 42
Und ersetzen durch:
quelle
Ich weiß, dass diese Frage ziemlich alt ist, aber es gibt eine ganz einfache Lösung dafür:
Sie müssen entweder den Json-Renderer ersetzen
Magento\Framework\Webapi\Rest\Response\Renderer\Json
oder ein Plugin dafür schreiben.Hier ein kleines Beispiel für ein Plugin:
In deinem
di.xml
In deiner neuen Plugin-Klasse
Namespace\Module\Plugin\Webapi\RestResponse\JsonPlugin
Was geschieht hier:
Natürlich können Sie auch Ihren eigenen Renderer schreiben, der beispielsweise ein Array verarbeitet.
quelle
Ich hatte das gleiche Problem und es dauerte eine Weile, bis ich das Problem herausgefunden hatte.
Magento macht etwas Seltsames in seinem Web-API-Service-Ausgabeprozessor, der sich unter Magento \ Framework \ Webapi \ ServiceOutputProcessor befindet. In dieser Klasse gibt es eine Methode namens convertValue (); Das ist der Grund für die [] Klammern.
Die beste Lösung für mich, um das Problem zu lösen, bestand darin, ein Around-Plugin zu erstellen, um diese if-Bedingung in convertValue () zu überwinden. Methode, bei der sie prüfen, ob $ data ein Array ist, und das seltsame Zeug damit machen.
Hier ist mein Beispielcode für das Plugin: Ich denke, jeder weiß, wie man ein Magento 2-Basismodul erstellt, daher poste ich hier nur den Code des Plugins.
Erstellen Sie einen Plugin-Ordner
Erstellen Sie eine Klasse Vendor \ ModuleName \ Plugin \ ServiceOutputProcessorPlugin.php
Dies sollte das Problem der Array-JSON-Ausgabe in der Web-API lösen
Hoffe das hilft
quelle