无需实体类实例化:通过字符串类名实现JSON反序列化
通用JSON反序列化实现(无需逐个声明实体类)
问题背景
需要反序列化对应多个数据库表的JSON文件,希望实现通用化方法,无需为每个表单独声明实体类。现有代码中尝试用字符串类名配合::class时触发错误:
Cannot use "::class" on value of type string
现有代码
public function readJsonFile(string $fileName, string $tableName) { $file = $this->projectDir . '/var/json-database/extranet_table_' . $fileName . '.json'; $fileString = file_get_contents($file); $fileObj = json_decode($fileString, true); return $this->convertJsonToObject($fileObj['data'], $fileName, $tableName); } private function convertJsonToObject(array $arrayData, string $fileName, string $tableName) { $arrayTableObj = []; foreach ($arrayData as $data) { $data['id'] = intval($data['id']); (isset($data['active'])) ? $data['active'] = true : $data['active'] = false; $dataJson = json_encode($data); $dataObj = $this->serializer->deserialize($dataJson, $tableName, 'json'); $arrayTableObj[] = $dataObj; } dd($arrayTableObj); }
解决方案
核心问题是Symfony Serializer的deserialize方法需要完整的类名(包含命名空间),而你传入的$tableName是短类名(如Language),且::class只能用于类常量,不能作用于字符串变量。
方案1:统一命名空间下拼接完整类名
如果所有实体类都在同一个命名空间(比如App\Entity\),直接拼接出完整类名即可:
private function convertJsonToObject(array $arrayData, string $fileName, string $tableName) { $arrayTableObj = []; // 拼接完整实体类名,根据你的实际命名空间调整 $fullEntityClass = 'App\\Entity\\' . $tableName; foreach ($arrayData as $data) { $data['id'] = intval($data['id']); $data['active'] = isset($data['active']) ? true : false; $dataJson = json_encode($data); // 使用完整类名进行反序列化 $dataObj = $this->serializer->deserialize($dataJson, $fullEntityClass, 'json'); $arrayTableObj[] = $dataObj; } dd($arrayTableObj); }
方案2:直接传入完整类名字符串
如果实体类的命名空间不固定,直接将完整类名作为$tableName参数传入(比如调用时传App\Entity\Language而非Language),这样无需拼接,直接使用:
// 调用示例 $this->readJsonFile('language', 'App\Entity\Language'); // convertJsonToObject方法中直接使用 $dataObj = $this->serializer->deserialize($dataJson, $tableName, 'json');
额外优化(可选)
无需先将数组转成JSON再反序列化,可直接使用denormalize方法提升效率:
$dataObj = $this->serializer->denormalize($data, $fullEntityClass);
内容的提问来源于stack exchange,提问作者Kulissu
相关产品推荐
相关产品推荐

