Reputation: 1
Is there a way to normalize (serialize and deserialize) object using Symfony Serializer (ObjectNormalizer) but by properties, not get/set/is... methods?
There is ObjectNormalizer but it's using get/set/is... methods, not declared properties, I have a lot of classes with logic to get something by get method, and I don't want to serialize them.
There is also PropertyNormalizer It serialize objects the way I want, but It cannot deserialize objects with objects as property. I get an error:
TypeError : Cannot assign array to property App\Shop\PageManagement\Factory\PageRowConfig\AbstractSliderConfig::$ctaUrl of type ?App\Shop\DTO\Url\UrlField
TypeError : Cannot assign array to property Foo\Bar::$property of type ?Foo/Bar/PropertyObject
I want to deserialize object with properties typed as another objects using SymfonySerializer but normalize it by property not get/set/is... methods.
class User
{
private string $name;
private string $surname;
/**
* @var Address[]
*/
private array $addresses;
public function getName(): string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
public function getSurname(): string
{
return $this->surname;
}
public function setSurname(string $surname): void
{
$this->surname = $surname;
}
public function getAddresses(): array
{
return $this->addresses;
}
public function setAddresses(array $addresses): void
{
$this->addresses = $addresses;
}
public function getFullName(): string
{
return $this->name . ' ' . $this->surname;
}
public function getType(): string
{
return 'sometype';
}
}
abstract class SimpleAddress
{
private string $city;
public function getCity(): string
{
return $this->city;
}
public function setCity(string $city): void
{
$this->city = $city;
}
}
class Address extends SimpleAddress
{
private AddressTypeEnum $addressType;
private string $street;
public function getAddressType(): AddressTypeEnum
{
return $this->addressType;
}
public function setAddressType(AddressTypeEnum $addressType): void
{
$this->addressType = $addressType;
}
public function getStreet(): string
{
return $this->street;
}
public function setStreet(string $street): void
{
$this->street = $street;
}
public function getFullAddress(): string
{
return $this->getCity() . ' ' . $this->street;
}
}
use MabeEnum\Enum;
use MabeEnum\EnumSerializableTrait;
class AddressTypeEnum extends Enum implements \Serializable
{
use EnumSerializableTrait;
public const WORK = 'Work';
public const HOME = 'Home';
public static function Work(): self
{
return self::get(self::WORK);
}
public static function HOME(): self
{
return self::get(self::HOME);
}
}
And this is the result I want to get.
{
"user": {
"name": "Tom",
"surname": "Tailor",
"addresses": [
{
"addressType": "Work",
"city": "LA",
"street": "Central"
},
{
"addressType": "Home",
"city": "Washington",
"street": "Some street"
}
]
}
}
And I can serialize it by PropertyNormalizer,but i cannot deserialize.
Upvotes: 0
Views: 995
Reputation: 866
Your example works for me. No TypeError. So I wonder if I have understood your challenge.
I need to remove "user": {} so I can test it. The property user seems to be part of another object.
$json = '{
"name": "Tom",
"surname": "Tailor",
"addresses": [
{
"addressType": "Work",
"city": "LA",
"street": "Central"
},
{
"addressType": "Home",
"city": "Washington",
"street": "Some street"
}
]
}';
That's how I deserialize.
$serializer->deserialize($json, User::class, 'json');
The addresses are added as a multi-dimensional array:
If I add User::class addAddresses(), I have a collection of Addresses::class.
public function addAddresses(Address $address): void
{
$this->addresses[] = $address;
}
In the ReflectionExtractor (getTypes()), an attempt is made to resolve the type hint in a order.
The type is taken from addAddresses() and then the collection is set via setAddresses().
Upvotes: 0