Deserializing from JSON into PHP, with casting?
Suppose I have a User class with 'name' and 'password' properties, and a 'save' method. When serializing an object of this class to JSON via json_encode, the method is properly skipped and I end up with something like {'name': 'testName', 'password': 'testPassword'}.
However, when deserializing via json_decode, I end up with a StdClass object instead of a User object, which makes sense but this means the object lacks the 'save' method. Is there any way to cast the resultant object as a User, or to provide some hint to json_decode as to what type of object I'm expecting?
php json serialization
add a comment |
Suppose I have a User class with 'name' and 'password' properties, and a 'save' method. When serializing an object of this class to JSON via json_encode, the method is properly skipped and I end up with something like {'name': 'testName', 'password': 'testPassword'}.
However, when deserializing via json_decode, I end up with a StdClass object instead of a User object, which makes sense but this means the object lacks the 'save' method. Is there any way to cast the resultant object as a User, or to provide some hint to json_decode as to what type of object I'm expecting?
php json serialization
add a comment |
Suppose I have a User class with 'name' and 'password' properties, and a 'save' method. When serializing an object of this class to JSON via json_encode, the method is properly skipped and I end up with something like {'name': 'testName', 'password': 'testPassword'}.
However, when deserializing via json_decode, I end up with a StdClass object instead of a User object, which makes sense but this means the object lacks the 'save' method. Is there any way to cast the resultant object as a User, or to provide some hint to json_decode as to what type of object I'm expecting?
php json serialization
Suppose I have a User class with 'name' and 'password' properties, and a 'save' method. When serializing an object of this class to JSON via json_encode, the method is properly skipped and I end up with something like {'name': 'testName', 'password': 'testPassword'}.
However, when deserializing via json_decode, I end up with a StdClass object instead of a User object, which makes sense but this means the object lacks the 'save' method. Is there any way to cast the resultant object as a User, or to provide some hint to json_decode as to what type of object I'm expecting?
php json serialization
php json serialization
asked Mar 18 '09 at 14:25
Jeroen van DelftJeroen van Delft
1381111
1381111
add a comment |
add a comment |
11 Answers
11
active
oldest
votes
Old question, but maybe someone will find this useful.
I've created an abstract class with static functions that you can inherit on your object in order to deserialize any JSON into the inheriting class instance.
abstract class JsonDeserializer
{
/**
* @param string|array $json
* @return $this
*/
public static function Deserialize($json)
{
$className = get_called_class();
$classInstance = new $className();
if (is_string($json))
$json = json_decode($json);
foreach ($json as $key => $value) {
if (!property_exists($classInstance, $key)) continue;
$classInstance->{$key} = $value;
}
return $classInstance;
}
/**
* @param string $json
* @return $this
*/
public static function DeserializeArray($json)
{
$json = json_decode($json);
$items = ;
foreach ($json as $item)
$items = self::Deserialize($item);
return $items;
}
}
You use it by inheriting it on a class which has the values that your JSON will have:
class MyObject extends JsonDeserializer
{
/** @var string */
public $property1;
/** @var string */
public $property2;
/** @var string */
public $property3;
/** @var array */
public $array1;
}
Example usage:
$objectInstance = new MyObject();
$objectInstance->property1 = 'Value 1';
$objectInstance->property2 = 'Value 2';
$objectInstance->property3 = 'Value 3';
$objectInstance->array1 = ['Key 1' => 'Value 1', 'Key 2' => 'Value 2'];
$jsonSerialized = json_encode($objectInstance);
$deserializedInstance = MyObject::Deserialize($jsonSerialized);
You can use the ::DeserializeArray
method if your JSON contains an array of your target object.
Here's a runnable sample.
Excellent. I took part of your Deserialize() method and used it in my constructor which receives the JSON as a parameter. This way I can create new class, passing it in the JSON and the result is an instance of my class with the data populated in it. Thanks.
– Richard Moore
Aug 9 '17 at 16:40
add a comment |
Short answer: No (not that I know of*)
Long answer: json_encode will only serialize public variables. As you can see per the JSON spec, there is no "function" datatype. These are both reasons why your methods aren't serialized into your JSON object.
Ryan Graham is right - the only way to re-create these objects as non-stdClass instances is to re-create them post-deserialization.
Example
<?php
class Person
{
public $firstName;
public $lastName;
public function __construct( $firstName, $lastName )
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public static function createFromJson( $jsonString )
{
$object = json_decode( $jsonString );
return new self( $object->firstName, $object->lastName );
}
public function getName()
{
return $this->firstName . ' ' . $this->lastName;
}
}
$p = new Person( 'Peter', 'Bailey' );
$jsonPerson = json_encode( $p );
$reconstructedPerson = Person::createFromJson( $jsonPerson );
echo $reconstructedPerson->getName();
Alternatively, unless you really need the data as JSON, you can just use normal serialization and leverage the __sleep() and __wakeup() hooks to achieve additional customization.
*
In a previous question of my own it was suggested that you could implement some of the SPL interfaces to customize the input/output of json_encode() but my tests revealed those to be wild goose chases.
add a comment |
I think the best way to handle this would be via the constructor, either directly or via a factory:
class User
{
public $username;
public $nestedObj; //another class that has a constructor for handling json
...
// This could be make private if the factories below are used exclusively
// and then make more sane constructors like:
// __construct($username, $password)
public function __construct($mixed)
{
if (is_object($mixed)) {
if (isset($mixed->username))
$this->username = $mixed->username;
if (isset($mixed->nestedObj) && is_object($mixed->nestedObj))
$this->nestedObj = new NestedObject($mixed->nestedObj);
...
} else if (is_array($mixed)) {
if (isset($mixed['username']))
$this->username = $mixed['username'];
if (isset($mixed['nestedObj']) && is_array($mixed['nestedObj']))
$this->nestedObj = new NestedObj($mixed['nestedObj']);
...
}
}
...
public static fromJSON_by_obj($json)
{
return new self(json_decode($json));
}
public static fromJSON_by_ary($json)
{
return new self(json_decode($json, TRUE));
}
}
Exactly. JSON has no way of encoding what kind of object the original was.
– Powerlord
Mar 18 '09 at 14:33
add a comment |
You could create a FactoryClass of some sort:
function create(array $data)
{
$user = new User();
foreach($data as $k => $v) {
$user->$k = $v;
}
return $user;
}
It's not like the solution you wanted, but it gets your job done.
add a comment |
Have a look at this class I wrote:
https://github.com/mindplay-dk/jsonfreeze/blob/master/mindplay/jsonfreeze/JsonSerializer.php
It reserves a JSON object-property named '#type' to store the class-name, and it has some limitations that are described here:
Serialize/unserialize PHP object-graph to JSON
add a comment |
I'm aware that JSON doesn't support the serialization of functions, which is perfectly acceptable, and even desired. My classes are currently used as value objects in communicating with JavaScript, and functions would hold no meaning (and the regular serialization functions aren't usable).
However, as the functionality pertaining to these classes increases, encapsulating their utility functions (such as a User's save() in this case) inside the actual class makes sense to me. This does mean they're no longer strictly value objects though, and that's where I run into my aforementioned problem.
An idea I had would have the class name specified inside the JSON string, and would probably end up like this:
$string = '{"name": "testUser", "password": "testPassword", "class": "User"}';
$object = json_decode ($string);
$user = ($user->class) $object;
And the reverse would be setting the class property during/after json_encode. I know, a bit convoluted, but I'm just trying to keep related code together. I'll probably end up taking my utility functions out of the classes again; the modified constructor approach seems a bit opaque and runs into trouble with nested objects.
I do appreciate this and any future feedback, however.
Take a look at the J2EE world where you would create a separate class for encapsulating the operations you would be performing on the data-only object. In this case, maybe User and UserHandler.
– Ryan Graham
Mar 18 '09 at 15:35
I've updated my answer to address nested objects.
– Ryan Graham
Mar 18 '09 at 15:40
add a comment |
Bit late but another option is to use symfony serializer to deserialize xml, json, whatever to Object.
here is documentation:
http://symfony.com/doc/current/components/serializer.html#deserializing-in-an-existing-object
The only fully reusable solution of all answers, and very easy to apply. Should be the accepted answer!
– Devaro
Apr 11 '18 at 12:08
add a comment |
Maybe the hydration
pattern can be of help.
Basically you instantiate an new empty object (new User()
) and then you fill in the properties with values from the StdClass
object. For example you could have a hydrate
method in User
.
If possible in your case, you can make the User
constructor
accept an optional parameter of type StdClass
and take the values at instantiation.
add a comment |
To answer your direct question, no, there's no was to do this with json_encode/json_decode. JSON was designed and specified to be a format for encoding information, and not for serializing objects. The PHP function don't go beyond that.
If you're interested in recreating objects from JSON, one possible solution is a static method on all the objects in your hierarchy that accepts a stdClass/string and populates variables that looks something like this
//semi pseudo code, not tested
static public function createFromJson($json){
//if you pass in a string, decode it to an object
$json = is_string($json) ? json_decode($json) : $json;
foreach($json as $key=>$value){
$object = new self();
if(is_object($value)){
$object->{$key} = parent::createFromJson($json);
}
else{
$object->{$key} = $value;
}
}
return $object;
}
I didn't test that, but I hope it gets the idea across. Ideally, all your objects should extend from some base object (usually named "class Object") so you can add this code in one place only.
add a comment |
Below is an example of using both static (i.e. you know the class type in code) and dynamic (i.e. you only know the class type at runtime) to deserialize JSON back into a PHP object:
Code
<?php
class Car
{
private $brand;
private $model;
private $year;
public function __construct($brand, $model, $year)
{
$this->brand = $brand;
$this->model = $model;
$this->year = $year;
}
public function toJson()
{
$arr = array(
'brand' => $this->brand,
'model' => $this->model,
'year' => $this->year,
);
return json_encode($arr);
}
public static function fromJson($json)
{
$arr = json_decode($json, true);
return new self(
$arr['brand'],
$arr['model'],
$arr['year']
);
}
}
// original object
echo 'car1: ';
$car1 = new Car('Hyundai', 'Tucson', 2010);
var_dump($car1);
// serialize
echo 'car1class: ';
$car1class = get_class($car1); // need the class name for the dynamic case below. this would need to be bundled with the JSON to know what kind of class to recreate.
var_dump($car1class);
echo 'car1json: ';
$car1Json = $car1->toJson();
var_dump($car1Json);
// static recreation with direct invocation. can only do this if you know the class name in code.
echo 'car2: ';
$car2 = Car::fromJson($car1Json);
var_dump($car2);
// dynamic recreation with reflection. can do this when you only know the class name at runtime as a string.
echo 'car3: ';
$car3 = (new ReflectionMethod($car1class, 'fromJson'))->invoke(null, $car1Json);
var_dump($car3);
Output
car1: object(Car)#1 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
car1class: string(3) "Car"
car1json: string(48) "{"brand":"Hyundai","model":"Tucson","year":2010}"
car2: object(Car)#2 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
car3: object(Car)#4 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
add a comment |
I must say I am a bit dismayed that this isn't just standard, off the shelf functionality -- of some library, if not JSON itself. Why wouldn't you want to have essentially similar objects on both sides? (As far as JSON will let you, anyway)
Am I missing something here? Is there a library that does this? (AFAICT, none of [thrift, protocol buffers, avro] actually have API's for javascript. For my problem, I am most interested in JS <-> PHP, somewhat also in JS <-> python .)
Pure data formats, such as JSON or XML, deal only with the representation of data, not with the interpretation or meaning of the data - you can use these (or any number of other formats) to serialize objects (or any number of other things) but serialization itself is beyond the scope of generic data-formats.
– mindplay.dk
Feb 2 '14 at 20:55
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f658469%2fdeserializing-from-json-into-php-with-casting%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
11 Answers
11
active
oldest
votes
11 Answers
11
active
oldest
votes
active
oldest
votes
active
oldest
votes
Old question, but maybe someone will find this useful.
I've created an abstract class with static functions that you can inherit on your object in order to deserialize any JSON into the inheriting class instance.
abstract class JsonDeserializer
{
/**
* @param string|array $json
* @return $this
*/
public static function Deserialize($json)
{
$className = get_called_class();
$classInstance = new $className();
if (is_string($json))
$json = json_decode($json);
foreach ($json as $key => $value) {
if (!property_exists($classInstance, $key)) continue;
$classInstance->{$key} = $value;
}
return $classInstance;
}
/**
* @param string $json
* @return $this
*/
public static function DeserializeArray($json)
{
$json = json_decode($json);
$items = ;
foreach ($json as $item)
$items = self::Deserialize($item);
return $items;
}
}
You use it by inheriting it on a class which has the values that your JSON will have:
class MyObject extends JsonDeserializer
{
/** @var string */
public $property1;
/** @var string */
public $property2;
/** @var string */
public $property3;
/** @var array */
public $array1;
}
Example usage:
$objectInstance = new MyObject();
$objectInstance->property1 = 'Value 1';
$objectInstance->property2 = 'Value 2';
$objectInstance->property3 = 'Value 3';
$objectInstance->array1 = ['Key 1' => 'Value 1', 'Key 2' => 'Value 2'];
$jsonSerialized = json_encode($objectInstance);
$deserializedInstance = MyObject::Deserialize($jsonSerialized);
You can use the ::DeserializeArray
method if your JSON contains an array of your target object.
Here's a runnable sample.
Excellent. I took part of your Deserialize() method and used it in my constructor which receives the JSON as a parameter. This way I can create new class, passing it in the JSON and the result is an instance of my class with the data populated in it. Thanks.
– Richard Moore
Aug 9 '17 at 16:40
add a comment |
Old question, but maybe someone will find this useful.
I've created an abstract class with static functions that you can inherit on your object in order to deserialize any JSON into the inheriting class instance.
abstract class JsonDeserializer
{
/**
* @param string|array $json
* @return $this
*/
public static function Deserialize($json)
{
$className = get_called_class();
$classInstance = new $className();
if (is_string($json))
$json = json_decode($json);
foreach ($json as $key => $value) {
if (!property_exists($classInstance, $key)) continue;
$classInstance->{$key} = $value;
}
return $classInstance;
}
/**
* @param string $json
* @return $this
*/
public static function DeserializeArray($json)
{
$json = json_decode($json);
$items = ;
foreach ($json as $item)
$items = self::Deserialize($item);
return $items;
}
}
You use it by inheriting it on a class which has the values that your JSON will have:
class MyObject extends JsonDeserializer
{
/** @var string */
public $property1;
/** @var string */
public $property2;
/** @var string */
public $property3;
/** @var array */
public $array1;
}
Example usage:
$objectInstance = new MyObject();
$objectInstance->property1 = 'Value 1';
$objectInstance->property2 = 'Value 2';
$objectInstance->property3 = 'Value 3';
$objectInstance->array1 = ['Key 1' => 'Value 1', 'Key 2' => 'Value 2'];
$jsonSerialized = json_encode($objectInstance);
$deserializedInstance = MyObject::Deserialize($jsonSerialized);
You can use the ::DeserializeArray
method if your JSON contains an array of your target object.
Here's a runnable sample.
Excellent. I took part of your Deserialize() method and used it in my constructor which receives the JSON as a parameter. This way I can create new class, passing it in the JSON and the result is an instance of my class with the data populated in it. Thanks.
– Richard Moore
Aug 9 '17 at 16:40
add a comment |
Old question, but maybe someone will find this useful.
I've created an abstract class with static functions that you can inherit on your object in order to deserialize any JSON into the inheriting class instance.
abstract class JsonDeserializer
{
/**
* @param string|array $json
* @return $this
*/
public static function Deserialize($json)
{
$className = get_called_class();
$classInstance = new $className();
if (is_string($json))
$json = json_decode($json);
foreach ($json as $key => $value) {
if (!property_exists($classInstance, $key)) continue;
$classInstance->{$key} = $value;
}
return $classInstance;
}
/**
* @param string $json
* @return $this
*/
public static function DeserializeArray($json)
{
$json = json_decode($json);
$items = ;
foreach ($json as $item)
$items = self::Deserialize($item);
return $items;
}
}
You use it by inheriting it on a class which has the values that your JSON will have:
class MyObject extends JsonDeserializer
{
/** @var string */
public $property1;
/** @var string */
public $property2;
/** @var string */
public $property3;
/** @var array */
public $array1;
}
Example usage:
$objectInstance = new MyObject();
$objectInstance->property1 = 'Value 1';
$objectInstance->property2 = 'Value 2';
$objectInstance->property3 = 'Value 3';
$objectInstance->array1 = ['Key 1' => 'Value 1', 'Key 2' => 'Value 2'];
$jsonSerialized = json_encode($objectInstance);
$deserializedInstance = MyObject::Deserialize($jsonSerialized);
You can use the ::DeserializeArray
method if your JSON contains an array of your target object.
Here's a runnable sample.
Old question, but maybe someone will find this useful.
I've created an abstract class with static functions that you can inherit on your object in order to deserialize any JSON into the inheriting class instance.
abstract class JsonDeserializer
{
/**
* @param string|array $json
* @return $this
*/
public static function Deserialize($json)
{
$className = get_called_class();
$classInstance = new $className();
if (is_string($json))
$json = json_decode($json);
foreach ($json as $key => $value) {
if (!property_exists($classInstance, $key)) continue;
$classInstance->{$key} = $value;
}
return $classInstance;
}
/**
* @param string $json
* @return $this
*/
public static function DeserializeArray($json)
{
$json = json_decode($json);
$items = ;
foreach ($json as $item)
$items = self::Deserialize($item);
return $items;
}
}
You use it by inheriting it on a class which has the values that your JSON will have:
class MyObject extends JsonDeserializer
{
/** @var string */
public $property1;
/** @var string */
public $property2;
/** @var string */
public $property3;
/** @var array */
public $array1;
}
Example usage:
$objectInstance = new MyObject();
$objectInstance->property1 = 'Value 1';
$objectInstance->property2 = 'Value 2';
$objectInstance->property3 = 'Value 3';
$objectInstance->array1 = ['Key 1' => 'Value 1', 'Key 2' => 'Value 2'];
$jsonSerialized = json_encode($objectInstance);
$deserializedInstance = MyObject::Deserialize($jsonSerialized);
You can use the ::DeserializeArray
method if your JSON contains an array of your target object.
Here's a runnable sample.
edited Sep 28 '15 at 14:02
answered Sep 17 '15 at 14:29
René SackersRené Sackers
1,0841532
1,0841532
Excellent. I took part of your Deserialize() method and used it in my constructor which receives the JSON as a parameter. This way I can create new class, passing it in the JSON and the result is an instance of my class with the data populated in it. Thanks.
– Richard Moore
Aug 9 '17 at 16:40
add a comment |
Excellent. I took part of your Deserialize() method and used it in my constructor which receives the JSON as a parameter. This way I can create new class, passing it in the JSON and the result is an instance of my class with the data populated in it. Thanks.
– Richard Moore
Aug 9 '17 at 16:40
Excellent. I took part of your Deserialize() method and used it in my constructor which receives the JSON as a parameter. This way I can create new class, passing it in the JSON and the result is an instance of my class with the data populated in it. Thanks.
– Richard Moore
Aug 9 '17 at 16:40
Excellent. I took part of your Deserialize() method and used it in my constructor which receives the JSON as a parameter. This way I can create new class, passing it in the JSON and the result is an instance of my class with the data populated in it. Thanks.
– Richard Moore
Aug 9 '17 at 16:40
add a comment |
Short answer: No (not that I know of*)
Long answer: json_encode will only serialize public variables. As you can see per the JSON spec, there is no "function" datatype. These are both reasons why your methods aren't serialized into your JSON object.
Ryan Graham is right - the only way to re-create these objects as non-stdClass instances is to re-create them post-deserialization.
Example
<?php
class Person
{
public $firstName;
public $lastName;
public function __construct( $firstName, $lastName )
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public static function createFromJson( $jsonString )
{
$object = json_decode( $jsonString );
return new self( $object->firstName, $object->lastName );
}
public function getName()
{
return $this->firstName . ' ' . $this->lastName;
}
}
$p = new Person( 'Peter', 'Bailey' );
$jsonPerson = json_encode( $p );
$reconstructedPerson = Person::createFromJson( $jsonPerson );
echo $reconstructedPerson->getName();
Alternatively, unless you really need the data as JSON, you can just use normal serialization and leverage the __sleep() and __wakeup() hooks to achieve additional customization.
*
In a previous question of my own it was suggested that you could implement some of the SPL interfaces to customize the input/output of json_encode() but my tests revealed those to be wild goose chases.
add a comment |
Short answer: No (not that I know of*)
Long answer: json_encode will only serialize public variables. As you can see per the JSON spec, there is no "function" datatype. These are both reasons why your methods aren't serialized into your JSON object.
Ryan Graham is right - the only way to re-create these objects as non-stdClass instances is to re-create them post-deserialization.
Example
<?php
class Person
{
public $firstName;
public $lastName;
public function __construct( $firstName, $lastName )
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public static function createFromJson( $jsonString )
{
$object = json_decode( $jsonString );
return new self( $object->firstName, $object->lastName );
}
public function getName()
{
return $this->firstName . ' ' . $this->lastName;
}
}
$p = new Person( 'Peter', 'Bailey' );
$jsonPerson = json_encode( $p );
$reconstructedPerson = Person::createFromJson( $jsonPerson );
echo $reconstructedPerson->getName();
Alternatively, unless you really need the data as JSON, you can just use normal serialization and leverage the __sleep() and __wakeup() hooks to achieve additional customization.
*
In a previous question of my own it was suggested that you could implement some of the SPL interfaces to customize the input/output of json_encode() but my tests revealed those to be wild goose chases.
add a comment |
Short answer: No (not that I know of*)
Long answer: json_encode will only serialize public variables. As you can see per the JSON spec, there is no "function" datatype. These are both reasons why your methods aren't serialized into your JSON object.
Ryan Graham is right - the only way to re-create these objects as non-stdClass instances is to re-create them post-deserialization.
Example
<?php
class Person
{
public $firstName;
public $lastName;
public function __construct( $firstName, $lastName )
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public static function createFromJson( $jsonString )
{
$object = json_decode( $jsonString );
return new self( $object->firstName, $object->lastName );
}
public function getName()
{
return $this->firstName . ' ' . $this->lastName;
}
}
$p = new Person( 'Peter', 'Bailey' );
$jsonPerson = json_encode( $p );
$reconstructedPerson = Person::createFromJson( $jsonPerson );
echo $reconstructedPerson->getName();
Alternatively, unless you really need the data as JSON, you can just use normal serialization and leverage the __sleep() and __wakeup() hooks to achieve additional customization.
*
In a previous question of my own it was suggested that you could implement some of the SPL interfaces to customize the input/output of json_encode() but my tests revealed those to be wild goose chases.
Short answer: No (not that I know of*)
Long answer: json_encode will only serialize public variables. As you can see per the JSON spec, there is no "function" datatype. These are both reasons why your methods aren't serialized into your JSON object.
Ryan Graham is right - the only way to re-create these objects as non-stdClass instances is to re-create them post-deserialization.
Example
<?php
class Person
{
public $firstName;
public $lastName;
public function __construct( $firstName, $lastName )
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public static function createFromJson( $jsonString )
{
$object = json_decode( $jsonString );
return new self( $object->firstName, $object->lastName );
}
public function getName()
{
return $this->firstName . ' ' . $this->lastName;
}
}
$p = new Person( 'Peter', 'Bailey' );
$jsonPerson = json_encode( $p );
$reconstructedPerson = Person::createFromJson( $jsonPerson );
echo $reconstructedPerson->getName();
Alternatively, unless you really need the data as JSON, you can just use normal serialization and leverage the __sleep() and __wakeup() hooks to achieve additional customization.
*
In a previous question of my own it was suggested that you could implement some of the SPL interfaces to customize the input/output of json_encode() but my tests revealed those to be wild goose chases.
edited May 23 '17 at 11:33
Community♦
11
11
answered Mar 18 '09 at 15:06
Peter BaileyPeter Bailey
93.9k25165192
93.9k25165192
add a comment |
add a comment |
I think the best way to handle this would be via the constructor, either directly or via a factory:
class User
{
public $username;
public $nestedObj; //another class that has a constructor for handling json
...
// This could be make private if the factories below are used exclusively
// and then make more sane constructors like:
// __construct($username, $password)
public function __construct($mixed)
{
if (is_object($mixed)) {
if (isset($mixed->username))
$this->username = $mixed->username;
if (isset($mixed->nestedObj) && is_object($mixed->nestedObj))
$this->nestedObj = new NestedObject($mixed->nestedObj);
...
} else if (is_array($mixed)) {
if (isset($mixed['username']))
$this->username = $mixed['username'];
if (isset($mixed['nestedObj']) && is_array($mixed['nestedObj']))
$this->nestedObj = new NestedObj($mixed['nestedObj']);
...
}
}
...
public static fromJSON_by_obj($json)
{
return new self(json_decode($json));
}
public static fromJSON_by_ary($json)
{
return new self(json_decode($json, TRUE));
}
}
Exactly. JSON has no way of encoding what kind of object the original was.
– Powerlord
Mar 18 '09 at 14:33
add a comment |
I think the best way to handle this would be via the constructor, either directly or via a factory:
class User
{
public $username;
public $nestedObj; //another class that has a constructor for handling json
...
// This could be make private if the factories below are used exclusively
// and then make more sane constructors like:
// __construct($username, $password)
public function __construct($mixed)
{
if (is_object($mixed)) {
if (isset($mixed->username))
$this->username = $mixed->username;
if (isset($mixed->nestedObj) && is_object($mixed->nestedObj))
$this->nestedObj = new NestedObject($mixed->nestedObj);
...
} else if (is_array($mixed)) {
if (isset($mixed['username']))
$this->username = $mixed['username'];
if (isset($mixed['nestedObj']) && is_array($mixed['nestedObj']))
$this->nestedObj = new NestedObj($mixed['nestedObj']);
...
}
}
...
public static fromJSON_by_obj($json)
{
return new self(json_decode($json));
}
public static fromJSON_by_ary($json)
{
return new self(json_decode($json, TRUE));
}
}
Exactly. JSON has no way of encoding what kind of object the original was.
– Powerlord
Mar 18 '09 at 14:33
add a comment |
I think the best way to handle this would be via the constructor, either directly or via a factory:
class User
{
public $username;
public $nestedObj; //another class that has a constructor for handling json
...
// This could be make private if the factories below are used exclusively
// and then make more sane constructors like:
// __construct($username, $password)
public function __construct($mixed)
{
if (is_object($mixed)) {
if (isset($mixed->username))
$this->username = $mixed->username;
if (isset($mixed->nestedObj) && is_object($mixed->nestedObj))
$this->nestedObj = new NestedObject($mixed->nestedObj);
...
} else if (is_array($mixed)) {
if (isset($mixed['username']))
$this->username = $mixed['username'];
if (isset($mixed['nestedObj']) && is_array($mixed['nestedObj']))
$this->nestedObj = new NestedObj($mixed['nestedObj']);
...
}
}
...
public static fromJSON_by_obj($json)
{
return new self(json_decode($json));
}
public static fromJSON_by_ary($json)
{
return new self(json_decode($json, TRUE));
}
}
I think the best way to handle this would be via the constructor, either directly or via a factory:
class User
{
public $username;
public $nestedObj; //another class that has a constructor for handling json
...
// This could be make private if the factories below are used exclusively
// and then make more sane constructors like:
// __construct($username, $password)
public function __construct($mixed)
{
if (is_object($mixed)) {
if (isset($mixed->username))
$this->username = $mixed->username;
if (isset($mixed->nestedObj) && is_object($mixed->nestedObj))
$this->nestedObj = new NestedObject($mixed->nestedObj);
...
} else if (is_array($mixed)) {
if (isset($mixed['username']))
$this->username = $mixed['username'];
if (isset($mixed['nestedObj']) && is_array($mixed['nestedObj']))
$this->nestedObj = new NestedObj($mixed['nestedObj']);
...
}
}
...
public static fromJSON_by_obj($json)
{
return new self(json_decode($json));
}
public static fromJSON_by_ary($json)
{
return new self(json_decode($json, TRUE));
}
}
edited Mar 18 '09 at 15:40
answered Mar 18 '09 at 14:31
Ryan GrahamRyan Graham
7,02612230
7,02612230
Exactly. JSON has no way of encoding what kind of object the original was.
– Powerlord
Mar 18 '09 at 14:33
add a comment |
Exactly. JSON has no way of encoding what kind of object the original was.
– Powerlord
Mar 18 '09 at 14:33
Exactly. JSON has no way of encoding what kind of object the original was.
– Powerlord
Mar 18 '09 at 14:33
Exactly. JSON has no way of encoding what kind of object the original was.
– Powerlord
Mar 18 '09 at 14:33
add a comment |
You could create a FactoryClass of some sort:
function create(array $data)
{
$user = new User();
foreach($data as $k => $v) {
$user->$k = $v;
}
return $user;
}
It's not like the solution you wanted, but it gets your job done.
add a comment |
You could create a FactoryClass of some sort:
function create(array $data)
{
$user = new User();
foreach($data as $k => $v) {
$user->$k = $v;
}
return $user;
}
It's not like the solution you wanted, but it gets your job done.
add a comment |
You could create a FactoryClass of some sort:
function create(array $data)
{
$user = new User();
foreach($data as $k => $v) {
$user->$k = $v;
}
return $user;
}
It's not like the solution you wanted, but it gets your job done.
You could create a FactoryClass of some sort:
function create(array $data)
{
$user = new User();
foreach($data as $k => $v) {
$user->$k = $v;
}
return $user;
}
It's not like the solution you wanted, but it gets your job done.
answered Mar 18 '09 at 16:47
boukebouke
7,32354174
7,32354174
add a comment |
add a comment |
Have a look at this class I wrote:
https://github.com/mindplay-dk/jsonfreeze/blob/master/mindplay/jsonfreeze/JsonSerializer.php
It reserves a JSON object-property named '#type' to store the class-name, and it has some limitations that are described here:
Serialize/unserialize PHP object-graph to JSON
add a comment |
Have a look at this class I wrote:
https://github.com/mindplay-dk/jsonfreeze/blob/master/mindplay/jsonfreeze/JsonSerializer.php
It reserves a JSON object-property named '#type' to store the class-name, and it has some limitations that are described here:
Serialize/unserialize PHP object-graph to JSON
add a comment |
Have a look at this class I wrote:
https://github.com/mindplay-dk/jsonfreeze/blob/master/mindplay/jsonfreeze/JsonSerializer.php
It reserves a JSON object-property named '#type' to store the class-name, and it has some limitations that are described here:
Serialize/unserialize PHP object-graph to JSON
Have a look at this class I wrote:
https://github.com/mindplay-dk/jsonfreeze/blob/master/mindplay/jsonfreeze/JsonSerializer.php
It reserves a JSON object-property named '#type' to store the class-name, and it has some limitations that are described here:
Serialize/unserialize PHP object-graph to JSON
edited May 23 '17 at 11:47
Community♦
11
11
answered Jul 16 '12 at 13:30
mindplay.dkmindplay.dk
4,99013240
4,99013240
add a comment |
add a comment |
I'm aware that JSON doesn't support the serialization of functions, which is perfectly acceptable, and even desired. My classes are currently used as value objects in communicating with JavaScript, and functions would hold no meaning (and the regular serialization functions aren't usable).
However, as the functionality pertaining to these classes increases, encapsulating their utility functions (such as a User's save() in this case) inside the actual class makes sense to me. This does mean they're no longer strictly value objects though, and that's where I run into my aforementioned problem.
An idea I had would have the class name specified inside the JSON string, and would probably end up like this:
$string = '{"name": "testUser", "password": "testPassword", "class": "User"}';
$object = json_decode ($string);
$user = ($user->class) $object;
And the reverse would be setting the class property during/after json_encode. I know, a bit convoluted, but I'm just trying to keep related code together. I'll probably end up taking my utility functions out of the classes again; the modified constructor approach seems a bit opaque and runs into trouble with nested objects.
I do appreciate this and any future feedback, however.
Take a look at the J2EE world where you would create a separate class for encapsulating the operations you would be performing on the data-only object. In this case, maybe User and UserHandler.
– Ryan Graham
Mar 18 '09 at 15:35
I've updated my answer to address nested objects.
– Ryan Graham
Mar 18 '09 at 15:40
add a comment |
I'm aware that JSON doesn't support the serialization of functions, which is perfectly acceptable, and even desired. My classes are currently used as value objects in communicating with JavaScript, and functions would hold no meaning (and the regular serialization functions aren't usable).
However, as the functionality pertaining to these classes increases, encapsulating their utility functions (such as a User's save() in this case) inside the actual class makes sense to me. This does mean they're no longer strictly value objects though, and that's where I run into my aforementioned problem.
An idea I had would have the class name specified inside the JSON string, and would probably end up like this:
$string = '{"name": "testUser", "password": "testPassword", "class": "User"}';
$object = json_decode ($string);
$user = ($user->class) $object;
And the reverse would be setting the class property during/after json_encode. I know, a bit convoluted, but I'm just trying to keep related code together. I'll probably end up taking my utility functions out of the classes again; the modified constructor approach seems a bit opaque and runs into trouble with nested objects.
I do appreciate this and any future feedback, however.
Take a look at the J2EE world where you would create a separate class for encapsulating the operations you would be performing on the data-only object. In this case, maybe User and UserHandler.
– Ryan Graham
Mar 18 '09 at 15:35
I've updated my answer to address nested objects.
– Ryan Graham
Mar 18 '09 at 15:40
add a comment |
I'm aware that JSON doesn't support the serialization of functions, which is perfectly acceptable, and even desired. My classes are currently used as value objects in communicating with JavaScript, and functions would hold no meaning (and the regular serialization functions aren't usable).
However, as the functionality pertaining to these classes increases, encapsulating their utility functions (such as a User's save() in this case) inside the actual class makes sense to me. This does mean they're no longer strictly value objects though, and that's where I run into my aforementioned problem.
An idea I had would have the class name specified inside the JSON string, and would probably end up like this:
$string = '{"name": "testUser", "password": "testPassword", "class": "User"}';
$object = json_decode ($string);
$user = ($user->class) $object;
And the reverse would be setting the class property during/after json_encode. I know, a bit convoluted, but I'm just trying to keep related code together. I'll probably end up taking my utility functions out of the classes again; the modified constructor approach seems a bit opaque and runs into trouble with nested objects.
I do appreciate this and any future feedback, however.
I'm aware that JSON doesn't support the serialization of functions, which is perfectly acceptable, and even desired. My classes are currently used as value objects in communicating with JavaScript, and functions would hold no meaning (and the regular serialization functions aren't usable).
However, as the functionality pertaining to these classes increases, encapsulating their utility functions (such as a User's save() in this case) inside the actual class makes sense to me. This does mean they're no longer strictly value objects though, and that's where I run into my aforementioned problem.
An idea I had would have the class name specified inside the JSON string, and would probably end up like this:
$string = '{"name": "testUser", "password": "testPassword", "class": "User"}';
$object = json_decode ($string);
$user = ($user->class) $object;
And the reverse would be setting the class property during/after json_encode. I know, a bit convoluted, but I'm just trying to keep related code together. I'll probably end up taking my utility functions out of the classes again; the modified constructor approach seems a bit opaque and runs into trouble with nested objects.
I do appreciate this and any future feedback, however.
answered Mar 18 '09 at 15:29
Jeroen van DelftJeroen van Delft
1381111
1381111
Take a look at the J2EE world where you would create a separate class for encapsulating the operations you would be performing on the data-only object. In this case, maybe User and UserHandler.
– Ryan Graham
Mar 18 '09 at 15:35
I've updated my answer to address nested objects.
– Ryan Graham
Mar 18 '09 at 15:40
add a comment |
Take a look at the J2EE world where you would create a separate class for encapsulating the operations you would be performing on the data-only object. In this case, maybe User and UserHandler.
– Ryan Graham
Mar 18 '09 at 15:35
I've updated my answer to address nested objects.
– Ryan Graham
Mar 18 '09 at 15:40
Take a look at the J2EE world where you would create a separate class for encapsulating the operations you would be performing on the data-only object. In this case, maybe User and UserHandler.
– Ryan Graham
Mar 18 '09 at 15:35
Take a look at the J2EE world where you would create a separate class for encapsulating the operations you would be performing on the data-only object. In this case, maybe User and UserHandler.
– Ryan Graham
Mar 18 '09 at 15:35
I've updated my answer to address nested objects.
– Ryan Graham
Mar 18 '09 at 15:40
I've updated my answer to address nested objects.
– Ryan Graham
Mar 18 '09 at 15:40
add a comment |
Bit late but another option is to use symfony serializer to deserialize xml, json, whatever to Object.
here is documentation:
http://symfony.com/doc/current/components/serializer.html#deserializing-in-an-existing-object
The only fully reusable solution of all answers, and very easy to apply. Should be the accepted answer!
– Devaro
Apr 11 '18 at 12:08
add a comment |
Bit late but another option is to use symfony serializer to deserialize xml, json, whatever to Object.
here is documentation:
http://symfony.com/doc/current/components/serializer.html#deserializing-in-an-existing-object
The only fully reusable solution of all answers, and very easy to apply. Should be the accepted answer!
– Devaro
Apr 11 '18 at 12:08
add a comment |
Bit late but another option is to use symfony serializer to deserialize xml, json, whatever to Object.
here is documentation:
http://symfony.com/doc/current/components/serializer.html#deserializing-in-an-existing-object
Bit late but another option is to use symfony serializer to deserialize xml, json, whatever to Object.
here is documentation:
http://symfony.com/doc/current/components/serializer.html#deserializing-in-an-existing-object
answered Aug 16 '16 at 8:20
zajcazajca
82631835
82631835
The only fully reusable solution of all answers, and very easy to apply. Should be the accepted answer!
– Devaro
Apr 11 '18 at 12:08
add a comment |
The only fully reusable solution of all answers, and very easy to apply. Should be the accepted answer!
– Devaro
Apr 11 '18 at 12:08
The only fully reusable solution of all answers, and very easy to apply. Should be the accepted answer!
– Devaro
Apr 11 '18 at 12:08
The only fully reusable solution of all answers, and very easy to apply. Should be the accepted answer!
– Devaro
Apr 11 '18 at 12:08
add a comment |
Maybe the hydration
pattern can be of help.
Basically you instantiate an new empty object (new User()
) and then you fill in the properties with values from the StdClass
object. For example you could have a hydrate
method in User
.
If possible in your case, you can make the User
constructor
accept an optional parameter of type StdClass
and take the values at instantiation.
add a comment |
Maybe the hydration
pattern can be of help.
Basically you instantiate an new empty object (new User()
) and then you fill in the properties with values from the StdClass
object. For example you could have a hydrate
method in User
.
If possible in your case, you can make the User
constructor
accept an optional parameter of type StdClass
and take the values at instantiation.
add a comment |
Maybe the hydration
pattern can be of help.
Basically you instantiate an new empty object (new User()
) and then you fill in the properties with values from the StdClass
object. For example you could have a hydrate
method in User
.
If possible in your case, you can make the User
constructor
accept an optional parameter of type StdClass
and take the values at instantiation.
Maybe the hydration
pattern can be of help.
Basically you instantiate an new empty object (new User()
) and then you fill in the properties with values from the StdClass
object. For example you could have a hydrate
method in User
.
If possible in your case, you can make the User
constructor
accept an optional parameter of type StdClass
and take the values at instantiation.
answered Oct 4 '16 at 13:55
Mihai RăducanuMihai Răducanu
3,34431625
3,34431625
add a comment |
add a comment |
To answer your direct question, no, there's no was to do this with json_encode/json_decode. JSON was designed and specified to be a format for encoding information, and not for serializing objects. The PHP function don't go beyond that.
If you're interested in recreating objects from JSON, one possible solution is a static method on all the objects in your hierarchy that accepts a stdClass/string and populates variables that looks something like this
//semi pseudo code, not tested
static public function createFromJson($json){
//if you pass in a string, decode it to an object
$json = is_string($json) ? json_decode($json) : $json;
foreach($json as $key=>$value){
$object = new self();
if(is_object($value)){
$object->{$key} = parent::createFromJson($json);
}
else{
$object->{$key} = $value;
}
}
return $object;
}
I didn't test that, but I hope it gets the idea across. Ideally, all your objects should extend from some base object (usually named "class Object") so you can add this code in one place only.
add a comment |
To answer your direct question, no, there's no was to do this with json_encode/json_decode. JSON was designed and specified to be a format for encoding information, and not for serializing objects. The PHP function don't go beyond that.
If you're interested in recreating objects from JSON, one possible solution is a static method on all the objects in your hierarchy that accepts a stdClass/string and populates variables that looks something like this
//semi pseudo code, not tested
static public function createFromJson($json){
//if you pass in a string, decode it to an object
$json = is_string($json) ? json_decode($json) : $json;
foreach($json as $key=>$value){
$object = new self();
if(is_object($value)){
$object->{$key} = parent::createFromJson($json);
}
else{
$object->{$key} = $value;
}
}
return $object;
}
I didn't test that, but I hope it gets the idea across. Ideally, all your objects should extend from some base object (usually named "class Object") so you can add this code in one place only.
add a comment |
To answer your direct question, no, there's no was to do this with json_encode/json_decode. JSON was designed and specified to be a format for encoding information, and not for serializing objects. The PHP function don't go beyond that.
If you're interested in recreating objects from JSON, one possible solution is a static method on all the objects in your hierarchy that accepts a stdClass/string and populates variables that looks something like this
//semi pseudo code, not tested
static public function createFromJson($json){
//if you pass in a string, decode it to an object
$json = is_string($json) ? json_decode($json) : $json;
foreach($json as $key=>$value){
$object = new self();
if(is_object($value)){
$object->{$key} = parent::createFromJson($json);
}
else{
$object->{$key} = $value;
}
}
return $object;
}
I didn't test that, but I hope it gets the idea across. Ideally, all your objects should extend from some base object (usually named "class Object") so you can add this code in one place only.
To answer your direct question, no, there's no was to do this with json_encode/json_decode. JSON was designed and specified to be a format for encoding information, and not for serializing objects. The PHP function don't go beyond that.
If you're interested in recreating objects from JSON, one possible solution is a static method on all the objects in your hierarchy that accepts a stdClass/string and populates variables that looks something like this
//semi pseudo code, not tested
static public function createFromJson($json){
//if you pass in a string, decode it to an object
$json = is_string($json) ? json_decode($json) : $json;
foreach($json as $key=>$value){
$object = new self();
if(is_object($value)){
$object->{$key} = parent::createFromJson($json);
}
else{
$object->{$key} = $value;
}
}
return $object;
}
I didn't test that, but I hope it gets the idea across. Ideally, all your objects should extend from some base object (usually named "class Object") so you can add this code in one place only.
answered Mar 18 '09 at 17:09
Alan StormAlan Storm
129k70330506
129k70330506
add a comment |
add a comment |
Below is an example of using both static (i.e. you know the class type in code) and dynamic (i.e. you only know the class type at runtime) to deserialize JSON back into a PHP object:
Code
<?php
class Car
{
private $brand;
private $model;
private $year;
public function __construct($brand, $model, $year)
{
$this->brand = $brand;
$this->model = $model;
$this->year = $year;
}
public function toJson()
{
$arr = array(
'brand' => $this->brand,
'model' => $this->model,
'year' => $this->year,
);
return json_encode($arr);
}
public static function fromJson($json)
{
$arr = json_decode($json, true);
return new self(
$arr['brand'],
$arr['model'],
$arr['year']
);
}
}
// original object
echo 'car1: ';
$car1 = new Car('Hyundai', 'Tucson', 2010);
var_dump($car1);
// serialize
echo 'car1class: ';
$car1class = get_class($car1); // need the class name for the dynamic case below. this would need to be bundled with the JSON to know what kind of class to recreate.
var_dump($car1class);
echo 'car1json: ';
$car1Json = $car1->toJson();
var_dump($car1Json);
// static recreation with direct invocation. can only do this if you know the class name in code.
echo 'car2: ';
$car2 = Car::fromJson($car1Json);
var_dump($car2);
// dynamic recreation with reflection. can do this when you only know the class name at runtime as a string.
echo 'car3: ';
$car3 = (new ReflectionMethod($car1class, 'fromJson'))->invoke(null, $car1Json);
var_dump($car3);
Output
car1: object(Car)#1 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
car1class: string(3) "Car"
car1json: string(48) "{"brand":"Hyundai","model":"Tucson","year":2010}"
car2: object(Car)#2 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
car3: object(Car)#4 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
add a comment |
Below is an example of using both static (i.e. you know the class type in code) and dynamic (i.e. you only know the class type at runtime) to deserialize JSON back into a PHP object:
Code
<?php
class Car
{
private $brand;
private $model;
private $year;
public function __construct($brand, $model, $year)
{
$this->brand = $brand;
$this->model = $model;
$this->year = $year;
}
public function toJson()
{
$arr = array(
'brand' => $this->brand,
'model' => $this->model,
'year' => $this->year,
);
return json_encode($arr);
}
public static function fromJson($json)
{
$arr = json_decode($json, true);
return new self(
$arr['brand'],
$arr['model'],
$arr['year']
);
}
}
// original object
echo 'car1: ';
$car1 = new Car('Hyundai', 'Tucson', 2010);
var_dump($car1);
// serialize
echo 'car1class: ';
$car1class = get_class($car1); // need the class name for the dynamic case below. this would need to be bundled with the JSON to know what kind of class to recreate.
var_dump($car1class);
echo 'car1json: ';
$car1Json = $car1->toJson();
var_dump($car1Json);
// static recreation with direct invocation. can only do this if you know the class name in code.
echo 'car2: ';
$car2 = Car::fromJson($car1Json);
var_dump($car2);
// dynamic recreation with reflection. can do this when you only know the class name at runtime as a string.
echo 'car3: ';
$car3 = (new ReflectionMethod($car1class, 'fromJson'))->invoke(null, $car1Json);
var_dump($car3);
Output
car1: object(Car)#1 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
car1class: string(3) "Car"
car1json: string(48) "{"brand":"Hyundai","model":"Tucson","year":2010}"
car2: object(Car)#2 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
car3: object(Car)#4 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
add a comment |
Below is an example of using both static (i.e. you know the class type in code) and dynamic (i.e. you only know the class type at runtime) to deserialize JSON back into a PHP object:
Code
<?php
class Car
{
private $brand;
private $model;
private $year;
public function __construct($brand, $model, $year)
{
$this->brand = $brand;
$this->model = $model;
$this->year = $year;
}
public function toJson()
{
$arr = array(
'brand' => $this->brand,
'model' => $this->model,
'year' => $this->year,
);
return json_encode($arr);
}
public static function fromJson($json)
{
$arr = json_decode($json, true);
return new self(
$arr['brand'],
$arr['model'],
$arr['year']
);
}
}
// original object
echo 'car1: ';
$car1 = new Car('Hyundai', 'Tucson', 2010);
var_dump($car1);
// serialize
echo 'car1class: ';
$car1class = get_class($car1); // need the class name for the dynamic case below. this would need to be bundled with the JSON to know what kind of class to recreate.
var_dump($car1class);
echo 'car1json: ';
$car1Json = $car1->toJson();
var_dump($car1Json);
// static recreation with direct invocation. can only do this if you know the class name in code.
echo 'car2: ';
$car2 = Car::fromJson($car1Json);
var_dump($car2);
// dynamic recreation with reflection. can do this when you only know the class name at runtime as a string.
echo 'car3: ';
$car3 = (new ReflectionMethod($car1class, 'fromJson'))->invoke(null, $car1Json);
var_dump($car3);
Output
car1: object(Car)#1 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
car1class: string(3) "Car"
car1json: string(48) "{"brand":"Hyundai","model":"Tucson","year":2010}"
car2: object(Car)#2 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
car3: object(Car)#4 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
Below is an example of using both static (i.e. you know the class type in code) and dynamic (i.e. you only know the class type at runtime) to deserialize JSON back into a PHP object:
Code
<?php
class Car
{
private $brand;
private $model;
private $year;
public function __construct($brand, $model, $year)
{
$this->brand = $brand;
$this->model = $model;
$this->year = $year;
}
public function toJson()
{
$arr = array(
'brand' => $this->brand,
'model' => $this->model,
'year' => $this->year,
);
return json_encode($arr);
}
public static function fromJson($json)
{
$arr = json_decode($json, true);
return new self(
$arr['brand'],
$arr['model'],
$arr['year']
);
}
}
// original object
echo 'car1: ';
$car1 = new Car('Hyundai', 'Tucson', 2010);
var_dump($car1);
// serialize
echo 'car1class: ';
$car1class = get_class($car1); // need the class name for the dynamic case below. this would need to be bundled with the JSON to know what kind of class to recreate.
var_dump($car1class);
echo 'car1json: ';
$car1Json = $car1->toJson();
var_dump($car1Json);
// static recreation with direct invocation. can only do this if you know the class name in code.
echo 'car2: ';
$car2 = Car::fromJson($car1Json);
var_dump($car2);
// dynamic recreation with reflection. can do this when you only know the class name at runtime as a string.
echo 'car3: ';
$car3 = (new ReflectionMethod($car1class, 'fromJson'))->invoke(null, $car1Json);
var_dump($car3);
Output
car1: object(Car)#1 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
car1class: string(3) "Car"
car1json: string(48) "{"brand":"Hyundai","model":"Tucson","year":2010}"
car2: object(Car)#2 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
car3: object(Car)#4 (3) {
["brand":"Car":private]=>
string(7) "Hyundai"
["model":"Car":private]=>
string(6) "Tucson"
["year":"Car":private]=>
int(2010)
}
answered Nov 15 '18 at 2:17
ryanbrainardryanbrainard
4,7652338
4,7652338
add a comment |
add a comment |
I must say I am a bit dismayed that this isn't just standard, off the shelf functionality -- of some library, if not JSON itself. Why wouldn't you want to have essentially similar objects on both sides? (As far as JSON will let you, anyway)
Am I missing something here? Is there a library that does this? (AFAICT, none of [thrift, protocol buffers, avro] actually have API's for javascript. For my problem, I am most interested in JS <-> PHP, somewhat also in JS <-> python .)
Pure data formats, such as JSON or XML, deal only with the representation of data, not with the interpretation or meaning of the data - you can use these (or any number of other formats) to serialize objects (or any number of other things) but serialization itself is beyond the scope of generic data-formats.
– mindplay.dk
Feb 2 '14 at 20:55
add a comment |
I must say I am a bit dismayed that this isn't just standard, off the shelf functionality -- of some library, if not JSON itself. Why wouldn't you want to have essentially similar objects on both sides? (As far as JSON will let you, anyway)
Am I missing something here? Is there a library that does this? (AFAICT, none of [thrift, protocol buffers, avro] actually have API's for javascript. For my problem, I am most interested in JS <-> PHP, somewhat also in JS <-> python .)
Pure data formats, such as JSON or XML, deal only with the representation of data, not with the interpretation or meaning of the data - you can use these (or any number of other formats) to serialize objects (or any number of other things) but serialization itself is beyond the scope of generic data-formats.
– mindplay.dk
Feb 2 '14 at 20:55
add a comment |
I must say I am a bit dismayed that this isn't just standard, off the shelf functionality -- of some library, if not JSON itself. Why wouldn't you want to have essentially similar objects on both sides? (As far as JSON will let you, anyway)
Am I missing something here? Is there a library that does this? (AFAICT, none of [thrift, protocol buffers, avro] actually have API's for javascript. For my problem, I am most interested in JS <-> PHP, somewhat also in JS <-> python .)
I must say I am a bit dismayed that this isn't just standard, off the shelf functionality -- of some library, if not JSON itself. Why wouldn't you want to have essentially similar objects on both sides? (As far as JSON will let you, anyway)
Am I missing something here? Is there a library that does this? (AFAICT, none of [thrift, protocol buffers, avro] actually have API's for javascript. For my problem, I am most interested in JS <-> PHP, somewhat also in JS <-> python .)
answered May 11 '10 at 22:04
Nick PapadakisNick Papadakis
11
11
Pure data formats, such as JSON or XML, deal only with the representation of data, not with the interpretation or meaning of the data - you can use these (or any number of other formats) to serialize objects (or any number of other things) but serialization itself is beyond the scope of generic data-formats.
– mindplay.dk
Feb 2 '14 at 20:55
add a comment |
Pure data formats, such as JSON or XML, deal only with the representation of data, not with the interpretation or meaning of the data - you can use these (or any number of other formats) to serialize objects (or any number of other things) but serialization itself is beyond the scope of generic data-formats.
– mindplay.dk
Feb 2 '14 at 20:55
Pure data formats, such as JSON or XML, deal only with the representation of data, not with the interpretation or meaning of the data - you can use these (or any number of other formats) to serialize objects (or any number of other things) but serialization itself is beyond the scope of generic data-formats.
– mindplay.dk
Feb 2 '14 at 20:55
Pure data formats, such as JSON or XML, deal only with the representation of data, not with the interpretation or meaning of the data - you can use these (or any number of other formats) to serialize objects (or any number of other things) but serialization itself is beyond the scope of generic data-formats.
– mindplay.dk
Feb 2 '14 at 20:55
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f658469%2fdeserializing-from-json-into-php-with-casting%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown