PHP中Cane类JSON序列化丢失父类Animale属性的解决方法
解决PHP继承类JSON序列化丢失父类属性的问题
这个问题的核心原因很明确:get_object_vars($this)只能获取当前类可见的属性。你的Animale类里的$id和$nome是private权限,子类Cane无法直接访问这些属性,所以当你在Cane的jsonSerialize里调用get_object_vars时,只能拿到Cane自己的$razza属性,父类的属性自然就丢失了。
下面给你两种实用的解决方案,你可以根据自己的代码场景选择:
方案一:调整父类属性权限 + 合并父类序列化结果
这是最简洁的方案,符合面向对象的设计思路:
- 把
Animale里的私有属性改成protected,这样子类可以访问到这些属性; - 在子类的
jsonSerialize方法里,先调用父类的序列化方法拿到父类属性,再和子类自己的属性合并。
完整代码示例:
class Animale implements \JsonSerializable{ // 把private改成protected,让子类能访问 protected $id; protected $nome; protected function Animale($id=-1,$nome="n/d"){ $this->id=$id; $this->nome=$nome; } public function jsonSerialize(){ return get_object_vars($this); } } class Cane extends Animale { private $razza; public function __construct($id=-1, $nome="n/d", $razza="n/d") { parent::Animale($id, $nome); $this->razza = $razza; } public function jsonSerialize() { // 合并父类和子类的属性数组 return array_merge(parent::jsonSerialize(), get_object_vars($this)); } }
测试一下:
$myDog = new Cane(1, "Buddy", "Golden Retriever"); echo json_encode($myDog); // 输出:{"id":1,"nome":"Buddy","razza":"Golden Retriever"}
方案二:用反射获取所有属性(无需修改父类)
如果不想改动父类的属性权限(比如父类是第三方代码不能修改),可以用PHP的反射机制来强制获取所有继承来的属性,包括私有属性:
class Animale implements \JsonSerializable{ private $id; private $nome; protected function Animale($id=-1,$nome="n/d"){ $this->id=$id; $this->nome=$nome; } public function jsonSerialize(){ return get_object_vars($this); } } class Cane extends Animale { private $razza; public function __construct($id=-1, $nome="n/d", $razza="n/d") { parent::Animale($id, $nome); $this->razza = $razza; } public function jsonSerialize() { $reflection = new \ReflectionClass($this); $allProperties = $reflection->getProperties(); $serializedData = []; foreach ($allProperties as $property) { // 强制设置属性可访问 $property->setAccessible(true); $serializedData[$property->getName()] = $property->getValue($this); } return $serializedData; } }
这个方案的原理是通过反射遍历当前对象的所有属性(不管是父类还是子类的,也不管权限是private/protected/public),强制读取它们的值,最后组装成序列化数组。
两种方案的对比
- 方案一:性能更好,代码简洁,推荐在你能修改父类代码的场景下使用;
- 方案二:更灵活,无需修改原有类结构,但反射会带来一定的性能开销,适合不能修改父类的场景。
内容的提问来源于stack exchange,提问作者giggiox
相关产品推荐
相关产品推荐

