如何让JMS/Serializer将属性反序列化为对象?ResponseStatus始终为数组的问题排查
问题:反序列化后
ResponseStatus始终是数组而非指定对象实例 你遇到的核心问题是混用了JMS Serializer的注解,但实际使用的是Symfony Serializer组件——这两个是完全独立的库,Symfony Serializer无法识别JMS的注解规则,所以它只会把嵌套的JSON结构转换成数组,而不会自动实例化SalesOrderGetResponseStatus对象。
下面给出两种可行的解决方案:
方案一:改用JMS Serializer的官方使用方式
既然你已经定义了JMS的注解,直接使用JMS Serializer库来处理序列化/反序列化是最直接的方式:
use JMS\Serializer\SerializerBuilder; // 正确初始化JMS Serializer实例 $serializer = SerializerBuilder::create() ->addDefaultHandlers() // 加载默认处理器,处理对象嵌套等场景 ->build(); // 直接反序列化为目标类实例,无需提前创建对象 $result = $serializer->deserialize($resultJson, SalesOrderGetResponse::class, 'json');
这样JMS Serializer会正确识别你定义的@Type注解,自动将ResponseStatus对应的JSON结构转换成SalesOrderGetResponseStatus对象。
方案二:切换为Symfony Serializer的注解体系
如果你更倾向于使用Symfony Serializer,需要把JMS的注解替换为Symfony Serializer自身的注解,并确保初始化时正确加载注解支持:
1. 修改实体类的注解
更新SalesOrderGetResponse类:
use Symfony\Component\Serializer\Annotation\Type; use Symfony\Component\Serializer\Annotation\SerializedName; class SalesOrderGetResponse { /** * @Type("array<Vendor\Module\Model\SalesOrder>") * @var SalesOrder[] */ public $mvSalesOrders = []; /** * @Type("Vendor\Module\Model\SalesOrderGetResponseStatus") * @SerializedName("ResponseStatus") // 显式声明属性与JSON键的对应关系,避免大小写等问题 * @var SalesOrderGetResponseStatus */ public $ResponseStatus; }
更新SalesOrderGetResponseStatus类:
use Symfony\Component\Serializer\Annotation\Type; class SalesOrderGetResponseStatus { const ERROR_CODE_SUCCESS = 0; /** * @Type("string") * @var string */ public $ErrorCode; }
2. 正确初始化Symfony Serializer
确保初始化时使用Symfony的注解加载器:
use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Encoder\JsonEncoder; use Doctrine\Common\Annotations\AnnotationReader; // 创建类元数据工厂,加载Symfony的注解 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); $normalizers = [new ObjectNormalizer($classMetadataFactory)]; $encoders = [new JsonEncoder()]; $serializer = new Serializer($normalizers, $encoders); // 执行反序列化 $result = new SalesOrderGetResponse(); $serializer->deserialize($resultJson, SalesOrderGetResponse::class, 'json', [ \Symfony\Component\Serializer\Normalizer\AbstractNormalizer::OBJECT_TO_POPULATE => $result ]);
这样Symfony Serializer就能识别@Type注解,将嵌套JSON结构转换成指定的对象实例了。
内容的提问来源于stack exchange,提问作者gabtzi
相关产品推荐
相关产品推荐

