I was trying to create a Payload where one of the fields is Collection of another objects. So I created something like this.
use DateTimeInterface;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Constraints\Collection;
class MyPayload
{
/**
* @var int
*
* @Serializer\Type("int")
* @Assert\Positive()
*/
private int $someNumber;
/**
* @var DateTimeInterface
*
* @Serializer\Type("DateTime<'Y-m-d'>")
*/
private DateTimeInterface $someDate;
/**
* @Assert\Collection(
* fields={
* "label"=@Assert\NotBlank(),
* "someNumber2"=@Assert\Positive(),
* }
* )
*/
private Collection $someCollection;
}
I'm sending something like this by postman (number of elements in some_collection is unknow, can be 1 can be 10):
{
"some_number": 123,
"some_date": "2021-01-01",
"some_collection": [
{
"label": "test1",
"some_number2": 10000
},
{
"label": "test2",
"some_number2": 15000
}
]
}
To my controller which looks like this:
/**
* @param MyPayload $myPayload
* @param ConstraintViolationListInterface $validationErrors
*
* @return JsonResponse
* @ParamConverter("myPayload", converter="fos_rest.request_body",
* class="App\Request\Payload\MyPayload")
*
*/
public function doSomething(
ContractPayload $myPayload,
ConstraintViolationListInterface $validationErrors
): JsonResponse {
try {
if (count($validationErrors) > 0) {
throw new ValidationException($validationErrors);
}
...
}
And the only answear I've got was :
'contractRate' - This value should be of type array|(Traversable&ArrayAccess).
I was looking for solution, but couldn't find any working one, do you know what to do to make it work?
your problem is exactly on the type you passed on the function, you passed ContractPayload instead of MyPayload, suddenly you will encounter another problem with serialization compared to the collection on the MyPayload type .. like that I made a little evolution hope that is clear.
First create a new type for collection it's usefull instead of collection of type any
<?php
namespace App\Request\Payload;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
class SomeItem
{
/**
* @Assert\NotBlank()
* @Serializer\Type("string")
*/
private $label;
/**
* @Assert\Positive()
* @Serializer\Type("int")
*/
private $someNumber2;
/**
* @return string
*/
public function getLabel():string
{
return $this->label;
}
/**
* @param string $label
*/
public function setLabel(string $label)
{
$this->label = $label;
}
/**
* @return int
*/
public function getSomeNumber2():int
{
return $this->someNumber2;
}
/**
* @param mixed $someNumber2
*/
public function setSomeNumber2(int $someNumber2)
{
$this->someNumber2 = $someNumber2;
}
}
make a little change on MyPayload
<?php
namespace App\Request\Payload;
use DateTimeInterface;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Constraints\Collection;
class MyPayload
{
/**
* @var int
*
* @Serializer\Type("int")
* @Assert\Positive()
*/
private int $someNumber;
/**
* @var DateTimeInterface
*
* @Serializer\Type("DateTime<'Y-m-d'>")
*/
private DateTimeInterface $someDate;
/**
* @Serializer\Type("ArrayCollection<App\Request\Payload\SomeItem>")
*/
private Collection $someCollection;
public function getSomeNumber():int
{
return $this->someNumber;
}
/**
* @param int $someNumber
*/
public function setSomeNumber(int $someNumber)
{
$this->someNumber = $someNumber;
}
/**
* @return DateTimeInterface
*/
public function getSomeDate():DateTimeInterface
{
return $this->someDate;
}
/**
* @param DateTimeInterface $someDate
*/
public function setSomeDate(DateTimeInterface $someDate)
{
$this->someDate = $someDate;
}
/**
* @return mixed
*/
public function getSomeCollection():Collection
{
return $this->someCollection;
}
// todo implmentation of add remove someItem ...;)
}
Last change ,Controller use App\Request\Payload\MyPayload; // ..
/**
* @param MyPayload $myPayload
* @param ConstraintViolationListInterface $validationErrors
*
* @return JsonResponse
* @ParamConverter("myPayload", converter="fos_rest.request_body", class="App\Request\Payload\MyPayload")
*
*/
public function doSomething(MyPayload $myPayload, ConstraintViolationListInterface $validationErrors): JsonResponse {
try {
if (count($validationErrors) > 0) {
throw new ValidationException($validationErrors);
}
...
}