Cyb10101
Cyb10101

Reputation: 385

Decode multiple model in php symfony from json to object

I would like to convert a json into a object / model. If the json is only one-dimensional, it works perfectly.

But if it is multidimensional, only the outer (user) is converted, but not the inner (company), this remains an array. Can you help me with this?

The Models:

<?php
namespace AppBundle;

class Company {
    /**
     * @var string
     */
    protected $companyName = '';

    /**
     * @return string
     */
    public function getCompanyName()
    {
        return $this->companyName;
    }

    /**
     * @param string $companyName
     * @return void
     */
    public function setCompanyName($companyName)
    {
        $this->companyName = $companyName;
    }
}

class User {
    /**
     * @var \AppBundle\Company
     */
    protected $company = null;

    /**
     * @var string
     */
    protected $username = '';

    /**
     * @return \AppBundle\Company
     */
    public function getCompany() {
        return $this->company;
    }

    /**
     * @param \AppBundle\Company $company
     * @return void
     */
    public function setCompany($company) {
        $this->company = $company;
    }

    /**
     * @return string
     */
    public function getUsername() {
        return $this->username;
    }

    /**
     * @param string $username
     * @return void
     */
    public function setUsername($username) {
        $this->username = $username;
    }
}
?>

Convert json to model:

<?php
namespace AppBundle\Controller;

class DefaultController extends \Symfony\Bundle\FrameworkBundle\Controller\Controller
{

    public function indexAction()
    {
        // Initialize serializer
        $objectNormalizer = new \Symfony\Component\Serializer\Normalizer\ObjectNormalizer();
        $jsonEncoder = new \Symfony\Component\Serializer\Encoder\JsonEncoder();
        $serializer = new \Symfony\Component\Serializer\Serializer([$objectNormalizer], [$jsonEncoder]);

        // Set test model
        $company = new \AppBundle\Company();
        $company->setCompanyName('MyCompany');
        $user = new \AppBundle\User();
        $user->setCompany($company);
        $user->setUsername('MyUsername');

        // Serialize test model to json
        $json = $serializer->serialize($user, 'json');
        dump($user); // Model ok, Company is instance of \AppBundle\Company
        dump($json); // json ok + valide

        // Deserialize json to model
        $user = $serializer->deserialize($json, \AppBundle\User::class, 'json');
        dump($user); // Error: Company is now array instead instance of \AppBundle\Company

        // Denormalize json to model
        $userArray = $serializer->decode($json, 'json');
        $user = $serializer->denormalize($userArray, \AppBundle\User::class);
        dump($user); // Error: Company is now array instead instance of \AppBundle\Company
    }
}
?>

Upvotes: 3

Views: 4641

Answers (1)

Cyb10101
Cyb10101

Reputation: 385

I solved the problem.

On the one hand you need PHP 7. Annotations I have not yet tested.

Then the variable has to be set correctly in setCompany().

public function setCompany(Company $company) {
    $this->company = $company;
}

And the ReflectionExtractor() must be used.

use Symfony\Component\Serializer\Normalizer;
use Symfony\Component\PropertyInfo\Extractor;
$objectNormalizer = new ObjectNormalizer(
    null,
    null,
    null,
    new ReflectionExtractor()
);

You only need deserialize(), because it decode() and denormalize(). http://symfony.com/doc/current/components/serializer.html

Full fixed code:

Company class:

class Company {
    /**
     * @var string
     */
    protected $companyName = '';

    /**
     * @return string
     */
    public function getCompanyName() {
        return $this->companyName;
    }

    /**
     * @param string $companyName
     * @return void
     */
    public function setCompanyName($companyName) {
        $this->companyName = $companyName;
    }
}

User class:

class User {
    /**
     * @var \AppBundle\Company
     */
    protected $company = null;

    /**
     * @var string
     */
    protected $username = '';

    /**
     * @return \AppBundle\Company
     */
    public function getCompany() {
        return $this->company;
    }

    /**
     * @param \AppBundle\Company $company
     * @return void
     */
    public function setCompany(Company $company) {
        $this->company = $company;
    }

    /**
     * @return string
     */
    public function getUsername() {
        return $this->username;
    }

    /**
     * @param string $username
     * @return void
     */
    public function setUsername($username) {
        $this->username = $username;
    }
}
?>

Controller class:

<?php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\Serializer\Normalizer;
use Symfony\Component\PropertyInfo\Extractor;
use Symfony\Component\Serializer;

class DefaultController extends Controller {
    public function indexAction() {
        $objectNormalizer = new ObjectNormalizer(
            null,
            null,
            null,
            new ReflectionExtractor()
        );
        $jsonEncoder = new JsonEncoder();
        $serializer = new Serializer([$objectNormalizer], [$jsonEncoder]);

        $company = new \AppBundle\Company();
        $company->setCompanyName('MyCompany');

        $user = new \AppBundle\User();
        $user->setCompany($company);
        $user->setUsername('MyUsername');

        $json = $serializer->serialize($user, 'json');
        dump($user, $json);

        $user2 = $serializer->deserialize($json, \AppBundle\User::class, 'json');
        dump($user2);
    }
}
?>

Upvotes: 6

Related Questions