I've run into an odd problem and I'm not sure how to fix it. I have several classes that are all PHP implementations of JSON objects. Here' an illustration of the issue
class A
{
protected $a;
public function __construct()
{
$this->a = array( new B, new B );
}
public function __toString()
{
return json_encode( $this->a );
}
}
class B
{
protected $b = array( 'foo' => 'bar' );
public function __toString()
{
return json_encode( $this->b );
}
}
$a = new A();
echo $a;
The output from this is
[{},{}]
When the desired output is
[{"foo":"bar"},{"foo":"bar"}]
The problem is that I was relying on the __toString() hook to do my work for me. But it can't, because the serialize that json_encode() uses won't call __toString(). When it encounters a nested object it simply serializes public properties only.
So, the question then become this: Is there a way I can develop a managed interface to JSON classes that both lets me use setters and getters for properties, but also allows me to get the JSON serialization behavior I desire?
If that's not clear, here's an example of an implementation that won't work, since the __set() hook is only called for the initial assignment
class a
{
public function __set( $prop, $value )
{
echo __METHOD__, PHP_EOL;
$this->$prop = $value;
}
public function __toString()
{
return json_encode( $this );
}
}
$a = new a;
$a->foo = 'bar';
$a->foo = 'baz';
echo $a;
I suppose I could also do something like this
class a
{
public $foo;
public function setFoo( $value )
{
$this->foo = $value;
}
public function __toString()
{
return json_encode( $this );
}
}
$a = new a;
$a->setFoo( 'bar' );
echo $a;
But then I would have to rely on the diligence of the other developers to use the setters - I can't force adherence programmtically with this solution.
---> EDIT <---
Now with a test of Rob Elsner's response
<?php
class a implements IteratorAggregate
{
public $foo = 'bar';
protected $bar = 'baz';
public function getIterator()
{
echo __METHOD__;
}
}
echo json_encode( new a );
When you execute this, you can see that the getIterator() method isn't ever invoked.
The json_encode() function is used to encode a value to JSON format.
To receive JSON string we can use the “php://input” along with the function file_get_contents() which helps us receive JSON data as a file and read it into a string. Later, we can use the json_decode() function to decode the JSON string.
Syntax. The json_encode() function can return a string containing the JSON representation of supplied value. The encoding is affected by supplied options, and additionally, the encoding of float values depends on the value of serialize_precision.
JSON data structures are very similar to PHP arrays. PHP has built-in functions to encode and decode JSON data. These functions are json_encode() and json_decode() , respectively. Both functions only works with UTF-8 encoded string data.
A late answers but might be useful for others with the same problem.
In PHP < 5.4.0 json_encode
doesn't call any method from the object. That is valid for getIterator, __serialize, etc...
In PHP > v5.4.0, however, a new interface was introduced, called JsonSerializable.
It basically controls the behaviour of the object when json_encode
is called on that object.
Example:
class A implements JsonSerializable
{
protected $a = array();
public function __construct()
{
$this->a = array( new B, new B );
}
public function jsonSerialize()
{
return $this->a;
}
}
class B implements JsonSerializable
{
protected $b = array( 'foo' => 'bar' );
public function jsonSerialize()
{
return $this->b;
}
}
$foo = new A();
$json = json_encode($foo);
var_dump($json);
Outputs:
string(29) "[{"foo":"bar"},{"foo":"bar"}]"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With