JMSSerializer 独立 - 注释不存在,或者无法自动加载

2022-08-30 12:32:38

我正在尝试使用JMSSerializer作为独立库,将JSON响应从API映射到我的模型类,并且遇到了一些问题。

执行以下代码会导致异常:

<?php
require dirname(__DIR__) . '/vendor/autoload.php';

use JMS\Serializer\Annotation AS JMS;

class Trii {
    /**
     * User ID for this session
     * @JMS\SerializedName("userID")
     * @JMS\Annotation(getter="getUserId")
     * @JMS\Type("string")
     * @var string
     */
    private $userId;

    public function getUserId() {
        return $this->userId;
    }

    public function setUserId($userId) {
        $this->userId = $userId;
    }
}

$serializer = \JMS\Serializer\SerializerBuilder::create()->setDebug(true)->build();
$object = $serializer->deserialize('{"userID":"Trii"}', 'Trii', 'json');
var_dump($object);
?>

这是例外

Doctrine\Common\Annotations\AnnotationException: [Semantical Error] The annotation "@JMS\Serializer\Annotation\SerializedName" in property Trii::$userId does not exist, or could not be auto-loaded.

我通过作曲家为该项目安装了以下库

{
    "require": {
        "jms/serializer": "1.0.*@dev"
    }
}

由于我没有使用整个教义2解决方案,我是否错过了一些明显的东西?

编辑:我的最终解决方案是创建一个包含以下内容的引导程序文件:

<?php
// standard composer install vendor autoload magic
require dirname(__DIR__) . '/vendor/autoload.php';

// Bootstrap the JMS custom annotations for Object to Json mapping
\Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace(
    'JMS\Serializer\Annotation',
    dirname(__DIR__).'/vendor/jms/serializer/src'
);
?>

答案 1

可以肯定的是,这可以实现静默自动加载,这比自己注册命名空间要方便得多。

AnnotationRegistry::registerLoader('class_exists');

答案 2

我遇到了同样的问题,并通过谷歌找到了你的问题。不幸的是,你还没有收到任何答案,所以我不得不自己深入研究。:P

问题是,JMSSerializer Annotations使用的 Doctrine Annotations不使用正常的PHP自动加载

如何加载这些注释?通过查看代码,您可以猜到ORM映射,断言验证和完全限定的注释可以使用定义的PHP自动加载器加载。然而,事实并非如此:由于错误处理原因,每次检查 AnnotationReader 中的类是否存在时都会将 class_exists($name, $autoload) 的第二个参数$autoload设置为 false。为了完美地工作,AnnotationReader需要静音自动加载器,而许多自动加载器则不是。静音自动加载不是 PSR-0 自动加载规范的一部分。

这意味着您必须自己注册注释文件:

AnnotationRegistry::registerFile(
   <PROJECT ROOT> . 
   "/vendor/jms/serializer/src/JMS/Serializer/Annotation/SerializedName.php");

...或整个命名空间(首选方法):

AnnotationRegistry::registerAutoloadNamespace(
    'JMS\Serializer\Annotation', 
    <PROJECT ROOT> . "/vendor/jms/serializer/src");

请注意 中的路径。我首先尝试以相同的方式注册注释的整个路径:registerAutoloadNamespaceregisterFile

<PROJECT ROOT> . "/vendor/jms/serializer/src/JMS/Serializer/Annotation 

但这失败了。:D

我希望这能让你更进一步。:)


推荐