Akbar Ali
Akbar Ali

Reputation: 305

getting garbage values while converting Yii model object to JSON


i have a model class which extends CComponent

    class CompanyModel extends CComponent{ 
    private $company_pk;
    public function getCompany_pk()
   {
        return $this->company_pk;
   }
   public function setCompany_pk($value)    {
        $this->company_pk = $value;
    }
}

I have a function which fills this modal

    public function getCompanyList() {
    $companyList=array();
    $company_obj = new CompanyModel();
    $sql = "SELECT company_pk,name FROM tbl_company WHERE status = ".Constants::ACTIVE_COMPANY;
    $command=$this->connection->createCommand($sql);
    $command->setFetchMode(PDO::FETCH_ASSOC);
    $rows=$command->queryAll();

    foreach ($rows as $row){
        $company_obj->company_pk = $row['company_pk'];
        array_push($companyList,$company_obj);

    }

    return $companyList;
}

and my controller

    Class UserController extends CController {
public  function actionGetCompanyList() {
    $model = new UserAction();
    $ret_val = $model->getCompanyList();
    echo CJSON::encode((array)$ret_val[0]);
         }
     }

and the JSON i get is

{"\u0000CompanyModel\u0000company_pk":"2"}

How can i remove those garbage values

Upvotes: 1

Views: 925

Answers (2)

Akbar Ali
Akbar Ali

Reputation: 305

I found out that if i extend CModel instead of CComponent in the model class, i could achieve what exactly i wanted. While extending this class you will have to override one abstract method. Otherwise it will throw error. My new Model class look like this

   class CompanyModel extends CModel{ 
private $company_pk;
public function attributeNames()
{
    return array( 'company_pk' );
}

public function attributeLabels()
{
    return array( 'company_pk' => 'company_pk Label' );
}
public function getCompany_pk()
   {
    return $this->company_pk;
   }
public function setCompany_pk($value)    {
    $this->company_pk = $value;
}
}

Upvotes: 0

Aurimas Ličkus
Aurimas Ličkus

Reputation: 10074

I asume you can't decode them later, if you would change $company_pk to public it should encode correctly. Problem is with your object cast to array which adds NULL byte to your private member $company_pk. In echo CJSON::encode((array)$ret_val[0]); as it's array of OBJECTS.

You can do nasty.

$json = '{"\u0000CompanyModel\u0000company_pk":"2"}';

$json = str_replace('\u0000', '', $json);

var_dump(json_decode($json));

Or you pass object to CJSON::encode i dont know much of YII but it should handle object, as per manual http://www.yiiframework.com/doc/api/1.1/CJSON.

Here is example to reproduce issue:

class test {
 private $private = 1;
 public $publiv = 2;
}

$obj = new test();
$array = (array) $obj;

$json = json_encode($array);

var_dump($json);

var_dump(json_decode($json));

EDIT:

From the manual http://www.php.net/manual/en/language.types.array.php:

If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible; private variables have the class name prepended to the variable name; protected variables have a '*' prepended to the variable name. These prepended values have null bytes on either side.

I did quick look to CJSON::encode from YII and you can use object directly, but your object must be traversable, so you must implement Iterator interface. http://www.php.net/manual/en/class.iterator.php.

EDIT:2

Implementing interface could be tricky, there is another option to call get_object_vars from within object and in this case you will get array which will work.

class CompanyModel extends CComponent
{
    private $company_pk;

    public function getCompany_pk()
    {
        return $this->company_pk;
    }
    public function setCompany_pk($value)
    {
        $this->company_pk = $value;
    }

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

}

And then:

$ret_val = $model->getCompanyList();
echo CJSON::encode($ret_val->export());

Problem why it does not work for you with normal object because YII uses get_object_vars internally and it can't access private properties when it's in different scope.

Upvotes: 1

Related Questions