For example I have SimpleDto class
class SimpleDto implements GetPhoneInterface
{
public string $name;
public int $value;
}
And json
{"name":"Jane"}
When I serialize it, i get not valid object.
$serializer = self::getContainer()->get(SerializerInterface::class);
$dto = $serializer->deserialize($json, $dtoClass);
$dto has not initial variable $value.
How can I make sure that during deserialization an exception occurs that the class has unvalidated values?
If this cannot be solved using a serializer, maybe there is some way to check using a validator?
Upd: I tried to implement it like this, but the code behaves incorrectly. In addition, ObjectNormalizer is a final class. Maybe someone knows a better solution?
class InitialObjectNormalizer extends ObjectNormalizer
{
// circle check
private array $visitedObjects = [];
private array $errors = [];
public function denormalize(mixed $data, string $type, ?string $format = null, array $context = [])
{
$data = parent::denormalize($data, $type, $format, $context);
$this->handleObject($data);
if (!empty($this->errors)) {
throw new PartialDenormalizationException(null, $this->errors);
}
return $data;
}
public function handleObject($obj): void
{
if (in_array($obj, $this->visitedObjects, true)) {
return;
}
$this->visitedObjects[] = $obj;
$attributes = new ReflectionObject($obj);
foreach ($attributes->getProperties() as $attribute) {
if (!$attribute->isInitialized($obj)) {
$this->errors[] = new NotNormalizableValueException('Attribute ' . $attribute->getName() . ' not initial',);
} else {
$value = $attribute->getValue($obj);
if (is_array($value) || is_object($value)) {
$this->handleObject($value);
}
}
}
}
}
Try rewriting your DTO using a constructor:
The standard
ObjectNormalizerwill now throw aMissingConstructorArgumentsExceptionwhich you can handle in your code.If you can not rewrite the DTO, you can implement a custom denormalizer and check whether all required fields are present. This is a very basic example, adapt to your own need.
You can find more about custom denormalizers in the Symfony documentation.