将php symfony中的多个模型从json解码为对象

Cyb*_*101 2 php json model decode symfony-3.1

我想将 json 转换为对象/模型。如果 json 只是一维的,它可以完美地工作。

但是如果它是多维的,则只转换外部(用户),而不转换内部(公司),这仍然是一个数组。你能帮我解决这个问题吗?

模型:

<?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;
    }
}
?>
Run Code Online (Sandbox Code Playgroud)

将json转换为模型:

<?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
    }
}
?>
Run Code Online (Sandbox Code Playgroud)

Cyb*_*101 5

我解决了这个问题。

一方面你需要 PHP 7。注释我还没有测试过。

然后必须在 setCompany() 中正确设置变量。

public function setCompany(Company $company) {
    $this->company = $company;
}
Run Code Online (Sandbox Code Playgroud)

并且必须使用 ReflectionExtractor()。

use Symfony\Component\Serializer\Normalizer;
use Symfony\Component\PropertyInfo\Extractor;
$objectNormalizer = new ObjectNormalizer(
    null,
    null,
    null,
    new ReflectionExtractor()
);
Run Code Online (Sandbox Code Playgroud)

你只需要deserialize(),因为它decode()denormalize()http://symfony.com/doc/current/components/serializer.html

完整的固定代码:

公司类:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

用户类:

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;
    }
}
?>
Run Code Online (Sandbox Code Playgroud)

控制器类:

<?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);
    }
}
?>
Run Code Online (Sandbox Code Playgroud)

  • 好一个。我还找到了`Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor`,它读取PHP Doc(`@var`)来获取类型,因此您可以将DTO 与公共属性一起使用,而无需强制类型化的getter/setter。 (3认同)