I want to send a JSON string via API, and then parse the JSON in code. I don't want Magento to try to convert my JSON parameter to a PHP object.
I'm trying to add this to the stock registry API. Here's the code that I've added.
webapi.xml
<route url="/V1/products/stockItems/update/" method="POST">
<service class="Magento\CatalogInventory\Api\StockRegistryInterface" method="updateStockItems"/>
<resources>
<resource ref="Magento_CatalogInventory::cataloginventory"/>
</resources>
</route>
StockRegistryInterface.php
public function updateStockItems($stockItems);
StockRegistry.php
public function updateStockItems($stockItems)
{
// do stuff
}
I'm posting to http://magento.test/rest/V1/products/stockItems/update
using Postman.
Here is my request address and headers.
Here's my JSON body
{
"stockItems": [
{
"item_id": 1,
"product_id": 1,
"stock_id": 1,
"qty": 15
},
{
"item_id": 2,
"product_id": 2,
"stock_id": 2,
"qty": 15
}
]
}
I'm getting the error
[2019-03-06 18:22:44] main.CRITICAL: Report ID: webapi-5c800ff4b4623;
Message: Class does not exist {"exception":"[object] (Exception(code: -1):
Report ID: webapi-5c800ff4b4623; Message: Class does not exist at
/var/www/magento2/lib/internal/Magento/Framework/Webapi/
ErrorProcessor.php:205, ReflectionException(code: -1):
Class does not exist at /var/www/magento2/lib/internal/Magento/Framework/
Webapi/ServiceInputProcessor.php:162)"} []
How do I get Magento to let me pass my JSON into updateStockItems
without trying to convert it to a Magento object?
Update
I can get it to work by passing my JSON as a string and then parsing that string into JSON in the PHP code. If I use the following as the body of my request, it works. But that seems like a dirty workaround. Is there a better way of doing it?
{ "stockItems": "[ {\"sku\": \"SKU-1234\", \"quantity\": 1234}, {\"sku\": \"SKU-5678\", \"quantity\": 5678} ]" }
And here's my PHP code (getStockItemBySku
is an existing Magento function within StockRegistry.php
)
public function updateStockItems($stockItems)
{
$json = json_decode($stockItems, true);
$updatedItemCount = 0;
foreach ($json as $productJson)
{
$sku = $productJson['sku'];
$quantity = $productJson['quantity'];
if ($sku !== NULL && $quantity != NULL)
{
$stockItem = $this->getStockItemBySku($sku);
if ($stockItem !== NULL)
{
$stockItem->setQty($quantity);
$this->stockItemRepository->save($stockItem);
$updatedItemCount++;
}
}
}
return $updatedItemCount;
}
Best Answer
I hope you don't have the intention to "hack" Magento core files. I recommend to create your own classes / interfaces for that!
Anyway if you are implementing a custom method
updateStockItems
for a webapi which updates more stockitems with a single request you should take care of the right method signature: You are expecting an array of stock items, therefore your input parameter should be of that type.Your interface:
Your method implementation:
Please take care to use only parameter in your JSON objects which match the used interfaces, in this example
\Magento\CatalogInventory\Api\Data\StockItemInterface
. So putting there some keysku
doesn't make sense and should either be ignored by Magento or give you an error in the API call.Here is the documentation about the usage of custom webservices.
https://devdocs.magento.com/guides/v2.3/extension-dev-guide/service-contracts/service-to-web-service.html