Convert json object in php

Asked

Viewed 4,534 times

4

I’m trying to create a class that saves objects like Conta in a json file, however, when saving to the file, the information of the object is not saved, it is just this:

[[],{}]

My class reading and saving in json is:

class JSONCustom {

    private $list = null;
    private $jsonFile = "teste.json";

    public function __construct() {
        if (file_exists($this->jsonFile)) {

            $string = file_get_contents($this->jsonFile);
            $json = json_decode($string, true);
            $this->list = $json;
        } else {
            $this->list = Array();
        }
    }

    public function getList() {

        return $this->list;
    }

    public function add($item) {
        //$jsonObject = get_object_vars($item);
        $this->list[] = $item;
        $this->save();
    }

    private function save() {
        if ($this->list != null) {
            $string = json_encode($this->list);
            file_put_contents($this->jsonFile, $string);
        }
    }
}

$agencia = new JSONCustom();

$conta = new Corrente(123, "teste", 3.10);
$agencia->add($conta);

var_dump($agencia->getList());

The Chain class:

class Corrente extends Conta{
    private $tarifaManutencao = 12.5;

    public function __construct($num, $prop, $saldo){
        parent::__construct($num, $prop, $saldo);
    }

    public function getTipoconta(){
        return "Corrente";
    }

    public function listarDados(){
        return parent::listarDados().
        "\nTipo de Conta: ".$this->getTipoconta().
        /* "\nTarifa de Manutencao: ".$this->tarifaManutencao; */
        "\nTarifa de Manutencao: ".CalcularFloat::formatarMoeda($this->tarifaManutencao);
    }

    public function cobrarTarifa(){
        if($this->getSaldo() < $this->tarifaManutencao){
            $this->habilitarPermissoesEspeciais();
            $this->sacar($this->tarifaManutencao);
            $this->desabilitarPermissoesEspeciais();
        }else{
            $this->sacar($this->tarifaManutencao);
        }
    }

    protected function setTarifaManutencao($novaTarifa){
        $this->tarifaManutencao = $novaTarifa;
    }
}

And my abstract class counts:

abstract class Conta{
    private $numero;
    private $proprietario;
    private $saldo;
    private $permissoesEspeciaisHabilitadas = false;

    public function __construct($num, $prop,$saldo){
        if($num < 0){
            throw new ExcecaoNumeroInvalido("Numero da conta nao pode ser negativo.");
        }else if($saldo < 0){
            throw new ExcecaoValorNegativo("Saldo nao pode ser negativo.");
        }
        $this->numero = $num;
        $this->proprietario = $prop;
        $this->saldo = $saldo;
    }

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

    public function getProprietario(){
        return $this->proprietario;
    }

    public function getSaldo(){
        return $this->saldo;
    }

    public function listarDados(){
        return "Numero: ".$this->numero.
        "\nNome: ".$this->proprietario.
        /* "\nSaldo: ".$this->getSaldo(); */
        "\nSaldo: ".CalcularFloat::formatarMoeda($this->getSaldo());
    }

    protected function permissoesEspeciaisHabilitadas(){
        return $this->permissoesEspeciaisHabilitadas;
    }

    public function habilitarPermissoesEspeciais(){
        $this->permissoesEspeciaisHabilitadas = true;
    }

    public function desabilitarPermissoesEspeciais(){
        $this->permissoesEspeciaisHabilitadas = false;
    }

    protected function verificarCondicoesParaSaque($valor){
        if ($valor < 0){
            throw new ExcecaoValorNegativo("Valor de saque nao pode ser negativo.");
        }else if($valor > $this->saldo && !$this->permissoesEspeciaisHabilitadas()){
            throw new ExcecaoSaqueInvalido("Sem saldo suficiente para este valor saque.");
        }
    }

    public function sacar($valor){
        $this->verificarCondicoesParaSaque($valor);
        $this->saldo = CalcularFloat::subtrair($this->saldo, $valor);
    }

    public function depositar($valor){
        if($valor < 0){
            throw new ExcecaoValorNegativo("Valor de deposito nao pode ser negativo.");
        }
        $this->saldo = CalcularFloat::somar($this->saldo, $valor);
    }

    public abstract function getTipoconta();
}

When executing a var_dump($agencia->getList()); the result returns the object normally:

array (size=3)
  0 => 
    array (size=0)
      empty
  1 => 
    array (size=0)
      empty
  2 => 
    object(Corrente)[2]
      private 'tarifaManutencao' => float 12.5
      private 'numero' (Conta) => int 123
      private 'proprietario' (Conta) => string 'teste' (length=5)
      private 'saldo' (Conta) => float 3.1
      private 'permissoesEspeciaisHabilitadas' (Conta) => boolean false

But when converting the json array to $string = json_encode($this->list); the array is not converted and saves only the quoted at the beginning of the question.

  • Have you used the print_r to see if the array is displayed correctly?

  • @Gilsones yes, look at the result of var_dump at the end of the question. The array is like this.

  • It’s just that on a you used $agencia->getList() and the other $this->list. I think it’s important to var_dump where you are trying to use json_encode. By the way, use print_r where json_encode is. At least for me it’s friendlier. then put also at the end of the post.

  • this happens because they are private objects. place them as "public"

3 answers

8


I managed to get all the attributes of my class Corrente and those inherited from the class Conta, adding the interface Jsonserialize in both classes, in accordance with soen reference quoted by @rray.

This interface forces you to implement the method jsonSerialize() that I added to the class Conta:

public function jsonSerialize() {
        return get_object_vars($this);
    }

And in class Corrente I did the same, however, by making a call from jsonSerialize() of the mother class, and then joining the resulting arrays of the two classes, containing all attributes of the two classes:

public function jsonSerialize() {
    $vars = array_merge(get_object_vars($this),parent::jsonSerialize());
    return $vars;
}

Now the object is being saved complete, see the output of the print_r:

[
  {
    "tarifaManutencao": 12.5,
    "numero": 123,
    "proprietario": "teste",
    "saldo": 3.1,
    "permissoesEspeciaisHabilitadas": false
  }
]

3

Private members are not converted by json_encode() your class in this case can implement a method that gets all the 'variables' of the class and returns a json.

Example that reproduces the error:

class Pessoa {
    private $id = 99;
    private $nome = 'teste';
    private $idade = 20;
}

echo json_encode(new Pessoa());

Example that works:

class Pessoa {
    private $id = 99;
    private $nome = 'teste';
    private $idade = 20;

    function serialize(){
        return json_encode(get_object_vars ($this));
    }   
}

$p = new Pessoa();
echo json_encode($p->serialize());

Reference

PHP json_encode class private Members

  • There’s a way I can intercept this similar to the to_string() of java?

  • 1

    Very cool @rray your answer and solution, did not know this solution using get_object_vars. +1

  • I understand from the Soen link that you added (I’m terrible in English hhehe), if you implement the interface JsonSerializable and the function of the same name, I would only need to change the class of the CURRENT object, that’s right?

  • @Diegofelipe, do yes, you make serialize() a private method and the implementation of toString() call him, to trigger it gets like this: $p = new Pessoa(); echo $p;, that way the code seems obscure to me.

  • @Diegofelipe, correct, remembering that this interface is available from version 5.4, ai you do the implementation of what you want to expose as json, can use get_object_vars().

  • I discovered a problem, when using this, it does not bring the attributes of the Account class, from which the Chain class is inheriting. I believe it is another question on this subject?

  • @Diegofelipe to weigh you here ... this code you played in the class Conta ?

  • I was able to solve it by following your tip from get_object_vars and the reporter who posted, I’ll post what I did.

Show 3 more comments

2

I’ve been through this problem and found this solution:

    if ($_GET['tipo'] == 'GET_OBJECT'){ 
        header("Content-type: application/json; charset=utf-8");
        $object = $_GET['object'];
        $objectController = new ObjectController();
        $objects = $objectController->getObjects($param);
        $lista_json = array("objects_array" => array());

        foreach($objects as $object){
            $obj = array (
                "attribute1" => $object->getAttribute()
            );

            array_push($lista_json["objects_array"], $obj);
        }
        echo json_encode($lista_json);
    }

I hope it’s the solution to your problem as well, although the code is completely different. I even check before the first IF which is the method, if it was a GET, PUT, DELETE, POST, but this part is no longer so important for your problem.

if ($_SERVER['REQUEST_METHOD'] == 'GET') {

    // Continuação do código, incluindo o código mencionado acima

}
  • Objectcontroller is a custom class of yours or php itself?

  • A custom class that performs CRUD operations, in addition to SELECT, with objects of a certain type.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.