Symfony序列化器-数组到对象的转换-每个字段的命名策略

时间:2018-12-04 10:43:31

标签: php symfony serialization jmsserializerbundle

我从外部API端点(例如Person API)获得了这样的数组,但是数组键名使用其他语言并且带有下划线-使用我的代码标准是不可接受的。该项目由Symfony 4.x和PHP 7.1运行

[
    'first_name_in_other_language' => 'value',
    'last_name_in_other_language' => 'value',
    ...more fields
]

但是我想将其转换为具有有效字段名称的类条目(例如:(Person不是教义实体-它是存储数据的简单对象)

class Person {private $firstName; private $lastName; ...more fields}

问题:我认为我应该制作某种映射器数组/对象,例如

['first_name_in_other_language' => 'firstName']

但是我找不到与Symfony相关的这种方法的任何示例 也许是因为这个问题与水化器而不是与序列化器有关?

我从zend hydrator找到了这段代码there,它似乎支持我需要的功能(new MapNamingStrategy(['published' => 'isPublished'])):

use Acme\Transaction;
use Zend\Hydrator\NamingStrategy\CompositeNamingStrategy;
use Zend\Hydrator\NamingStrategy\MapNamingStrategy;
use Zend\Hydrator\NamingStrategy\UnderscoreNamingStrategy;
use Zend\Hydrator\ObjectProperty as ObjectPropertyHydrator;

$underscoreNamingStrategy = new UnderscoreNamingStrategy();
$namingStrategy = new CompositeNamingStrategy([
    'isPublished' => new MapNamingStrategy(['published' => 'isPublished']),
    'publishedOn' => $underscoreNamingStrategy,
    'updatedOn'   => $underscoreNamingStrategy,
]);

$hydrator = new ObjectPropertyHydrator();
$hydrator->setNamingStrategy($namingStrategy);
$data = $hydrator->extract($transaction);

问题:可以使用Symfony序列化程序或其他Symfony组件对其进行存档吗?

2 个答案:

答案 0 :(得分:0)

如果我正确理解了您的问题,则可以为此类添加构造函数,如下所示:

class Person{
         private $firstName;
         private $lastName;
         //other stuff
         function __construct($your_api_answer){
            $this->firstName = $your_api_answer["first_name_key_of_answer"];
            $this->lastName = $your_api_answer["last_name_key_of_answer"];
            //initialize other stuff
         }
    }

$person = new Person($your_api_answer);

答案 1 :(得分:0)

这是一个可行的示例。

<?php
    
    namespace MyCompany\Bundle\SymfonyCustomerBundle\Formatter;
    
    use Symfony\Component\Serializer\Serializer;
    use Symfony\Component\Serializer\Encoder\JsonEncoder;
    use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
    use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
    use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
    use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
    use Doctrine\Common\Annotations\AnnotationReader;
    
    use Mycompany\Bundle\SymfonyCustomerBundle\Model\Contact;
    
    class ContactFormatter {
    
        public function __construct()
        {
            //TODO : Make it as a service injection for all formatter
            $classMetadataFactory = new ClassMetaDataFactory(
                new AnnotationLoader(new AnnotationReader())
            );
            $metadataAwareNameConverter = new MetadataAwareNameConverter($classMetadataFactory);
            $encoders = [new JsonEncoder()];
            $normalizers = [new ObjectNormalizer($classMetadataFactory, $metadataAwareNameConverter)];
    
            $this->serializer = new Serializer($normalizers, $encoders);
        }
    
        public function formatToModel(array $rawData): Contact
        {
            return $this->serializer->denormalize($rawData, Contact::class);
        }
    
        public function formatToArray(Contact $contact): array
        {   
            return $this->serializer->normalize($contact);
        }
    }

以及使用SerializedName批注的模型。

<?php

namespace Mycompany\Bundle\SymfonyCustomerBundle\Model;


use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Serializer\Annotation\SerializedName;

class Contact
{

    /**
     * @SerializedName("db_id_contact")
     */
    private int $idContact;

    /**
     * @SerializedName("db_nomContact")
     * @Assert\NotBlank
     */
    private ?string $lastName = null;
    
    /**
     * @SerializedName("db_prenomContact")
     * @Assert\NotBlank
     */
    private ?string $firstName = null;


    public function getIdContact(): int{
        return $this->idContact;
    }

    public function getLastName(): ?string {
        return $this->lastName;
    }

    public function getFirstName(): ?string {
        return $this->firstName;
    }

    public function setIdContact($value){
        $this->idContact = $value;
    }

    public function setLastName(?string $value){
        $this->lastName = $value;
    }

    public function setFirstName(?string $value){
        $this->firstName = $value;
    }
}