使用PHP中的类型将嵌套对象序列化/反序列化为JSON

时间:2015-11-16 09:03:46

标签: php json oop serialization

我有扩展抽象类的类。我需要通过字符串创建这些类的实例 - 最好是JSON。

许多对象都是嵌套的,许多属性都是私有的。我需要一种方法:

  1. 创建完整对象的JSON字符串(包含私有属性和嵌套对象 - 以及它们的私有属性)。
  2. 使用正确的类型和所有嵌套对象从JSON字符串创建新对象。
  3. 我想它需要递归。

    如果我只是将对象转换为数组,我正在使用最终看起来像垃圾的命名空间。

    我正在考虑编写一个解析器,在我的JSON字符串中标记类,然后为每个类硬编码一个工厂函数,但这需要花费很多时间。

4 个答案:

答案 0 :(得分:2)

我建议您使用php的serialize功能

在这种情况下,最好使用此函数,因为它存在于此目的:您可以将序列化字符串存储在任何位置,在反序列化之后,您将获得具有所有属性的原始PHP对象< / p>

正如你所说,使用JSON,你不知道对象是什么类(除非你手动将它存储为字符串),当然会有与私有属性相关的所有问题

答案 1 :(得分:2)

我建议使用jms序列化程序:http://jmsyst.com/libs/serializer 易于使用,可配置并支持您请求的所有功能。

答案 2 :(得分:1)

执行此操作有三种方法:JSON,Serialize和var_export。

使用JSON,它只能用于stdClass的对象,但它易于阅读,可以在PHP之外使用。

Serialize可以使用除stdClass之外的类的实例,但它可能很难读取,只能由PHP使用。 http://php.net/manual/en/function.serialize.php

var_export输出用于创建对象的PHP代码(因此您将其写入PHP文件),它非常易于阅读,但不能在PHP之外使用。对象需要具有set state方法。 http://php.net/manual/en/function.var-export.php

答案 3 :(得分:1)

您可以做的一件事是在每个要序列化和反序列化的类中使用魔术方法,方法是'__serialize()'和'__unserialize(array $ data)',__serialize返回具有属性的关联数组自己对象的对象就像getter,而__unserialize根据数组中的数据设置对象的状态就像setter!。 在一个显示下面的示例中,我曾经使用OOP来解决该问题。

这就像项目的主体,它所做的基本上是构建一个对象数组,并且该对象包含其他对象的数组,依此类推。 然后序列化所有包装的对象,然后使用__unserialize反序列化创建同一实例的另一个对象,并获得所有正确的信息 这里是。 注意:类cargarArchivo.php位于末尾,该类用于加载“省=>像美国的州一样”的哥斯达黎加政治部门的信息。以及与该省相关的数据。 查找文件'costaRica.xml&costaRica.json',信息将从该文件加载,并查找到gitHub存储库。 https://github.com/Gabriel-Barboza-Carvajal/Fetch-API-PHP-JSON/blob/master/servidor.php

include_once './modelo/division.php';
        include_once './modelo/canton.php';
        include_once './modelo/distrito.php';
        include_once './modelo/provincia.php';
        include_once './modelo/division_total.php';
        include_once './cargarArchivo.php';
       
        $divi=new division_total();
        $divi->provincias= cargarArchivo::devolverXMLCostaRica();
        //serializamos la informacion obtenida.
        $data = $divi->__serialize();
        
        //deserealizamos.
        $diviDeserea=new division_total();
        
        $diviDeserea->__unserialize($data);
        

abstract class division {

    private $numero, $nombre;
    

    public function __construct($numero, $nombre) {
        $this->numero = $numero;
        $this->nombre = $nombre;
    }


    public function __destruct() {
//        echo "<br>destruyendo obj general<br>";
    }

    public function getNumero() {
        return $this->numero;
    }

    public function getNombre() {
        return $this->nombre;
    }

    public function setNumero($numero) {
        $this->numero = $numero;
        return $this;
    }

    public function setNombre($nombre) {
        $this->nombre = $nombre;
        return $this;
    }
    
    abstract public function __serialize():array;
    abstract public function __unserialize(array $data):void;
    abstract public function __toString():string;
}
And the other classes the same like this...


class provincia extends division {

    public $cantones;

    public function __construct($num, $nom, $cant=null) {
        parent::__construct($num, $nom);
        $this->cantones = $cant;
    }

     public function __serialize(): array {
        return[
            'nombre' => $this->getNombre(),
            'número' => $this->getNumero(),
            'cantones' => $this->serializarCantones()
        ];
    }

    public function serializarCantones(): array {
        $todos = array();
        for ($index = 0; $index < count($this->cantones); $index++) {
            array_push($todos, ($this->cantones[$index])->__serialize());
        }
        return $todos;
    }

    public function __unserialize(array $data): void {
        $this->setNombre($data['nombre']);
        $this->setNumero($data['número']);
        $this->unserializarCantones($data);
    }
    
    public function unserializarCantones(array $data): void {
        $dis = $data['cantones'];
        $cont=0;
        foreach ($dis as $value) {
            $this->cantones[$cont] = new canton('', '');
            $this->cantones[$cont]->__unserialize($value);
            $cont+=1;
        }
    }

    public function __toString(): string {
        $str='';
        $str = '<br>' . $this->getNombre() . "|" . $this->getNumero() . '<br>';
        foreach ($this->cantones as $value) {
            $str .=$value->__toString();
        }
        return $str;
    }

}

class canton extends division {

    public $distritos;

    public function __construct($num, $nom, $distro = array()) {
        parent::__construct($num, $nom);
        $this->distritos = $distro;
    }

    public function agregarCantones($distritos) {
        $this->distritos = $distritos;
    }
    
    public function __serialize(): array {
        return[
            'nombre' => $this->getNombre(),
            'número' => $this->getNumero(),
            'distritos' => $this->serializarDistritos()
        ];
    }

    public function serializarDistritos(): array {
        $todos = array();
        for ($index = 0; $index < count($this->distritos); $index++) {
            array_push($todos, ($this->distritos[$index])->__serialize());
        }
        return $todos;
    }

    public function unserializarDistritos(array $data): void {
        $dis = $data['distritos'];
        $cont=0;
        foreach ($dis as $value) {
            $this->distritos[$cont] = new distrito('', '');
            $this->distritos[$cont]->__unserialize($value);
            $cont+=1;
        }
    }

    public function __unserialize(array $data): void {
        $this->setNombre($data['nombre']);
        $this->setNumero($data['número']);
        $this->unserializarDistritos($data);
    }

    public function __toString(): string {
        $str='';
        $str = '<br>' . $this->getNombre() . "|" . $this->getNumero() . '<br>';
        foreach ($this->distritos as $value) {
            $str .= $value->__toString();
        }
        return $str;
    }

}



class distrito extends division {

    private $secuencia;

    public function __construct($num = '', $nom = '', $sec = null) {
        parent::__construct($num, $nom);
        $this->secuencia = $sec;
    }

    public function getSecuencia() {
        return $this->secuencia;
    }

    public function setSecuencia($secuencia) {
        $this->secuencia = $secuencia;
        return $this;
    }

    public function __serialize(): array {
        return [
            'nombre'=> $this->getNombre(),
            'número'=> $this->getNumero(),
            'secuencia'=> $this->getSecuencia()
            ];
    }

    public function __unserialize(array $data): void {
        $this->secuencia=$data['secuencia'];
        $this->setNombre($data['nombre']);
        $this->setNumero($data['número']);
    }

    public function __toString(): string {
        $str='';
        $str= $this->getNombre() . ' , ' .$this->getNumero() . ' , ' . $this->getSecuencia();
        return $str;
    }

}
class division_total extends division{
    
    function __construct() {
        parent::__construct('0', 'Costa Rica');
    }

      public function __serialize(): array {
        return[
            'nombre' => $this->getNombre(),
            'número' => $this->getNumero(),
            'provincias' => $this->serializarProvincias()
        ];
    }

    public function serializarProvincias(): array {
        $todos = array();
        for ($index = 0; $index < count($this->provincias); $index++) {
            array_push($todos, ($this->provincias[$index])->__serialize());
        }
        return $todos;
    }

    public function __unserialize(array $data): void {
        $this->setNombre($data['nombre']);
        $this->setNumero($data['número']);
        $this->unserializarProvincias($data);
    }
    
    public function unserializarProvincias(array $data): void {
        $dis = $data['provincias'];
        $cont=0;
        foreach ($dis as $value) {
            $this->provincias[$cont] = new provincia('', '');
            $this->provincias[$cont]->__unserialize($value);
            $cont+=1;
        }
    }

    public function __toString(): string {
        $str='';
        $str = '<br>' . $this->getNombre() . "|" . $this->getNumero() . '<br>';
        foreach ($this->provincias as $value) {
            $str .=$value->__toString();
        }
        return $str;
    }

    public $provincias = array();
    
  
}
class cargarArchivo {

    public function __construct() {
        
    }

    static public function devolverXMLCostaRica() {
        libxml_use_internal_errors(true);
        $xml = simplexml_load_file('CostaRica.xml');
        if ($xml === false) {
            echo "Failed loading XML: ";
            foreach (libxml_get_errors() as $error) {
                echo "<br>", $error->message;
            }
        } else {
//            print_r($xml);
            //recorremos las provincias
            $divisionPolitica= array();
            foreach ($xml->children() as $data)
            {
                $nombre= $data['nombre'];
                $numero= $data['número'];
                $provin=new provincia($numero, $nombre);
                $cantones=array();
                array_push($divisionPolitica,$provin);//agregamos la provincia a la division politica.
                //recorremos el numero de cantones que tiene la provincia
                for ($index = 0; $index < $data->cantón->count(); $index++) {                    
                    $nomDistrCanton=$data->cantón[$index]['nombre'];
                    $numDistrCanton=$data->cantón[$index]->count();
                    $canton=new canton($numDistrCanton, $nomDistrCanton);
                    array_push($cantones,$canton);//agregamos un canton a la provincia
                    //ahora ocupamos recorrer todos los distritos que maneja este primer canton
                    $x=$data->cantón[$index];
                    $distritos=array();
                    for ($index1 = 0; $index1 < $data->cantón[$index]->count(); $index1++) {
                         $nom=$data->cantón[$index]->distrito['nombre'];
                         $num=$data->cantón[$index]->distrito['número'];
                         $sec=$data->cantón[$index]->distrito['secuencia'];
                        $distri=new distrito($num, $nom, $sec);
                        array_push($distritos,$distri);
                    }
                    $canton->distritos=$distritos;
                    $provin->cantones=$cantones;
                }
                
            }
            
            
            }
            
            
        
        return $divisionPolitica;
    }