Deserializing from JSON into PHP, with casting?












18















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?










share|improve this question



























    18















    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?










    share|improve this question

























      18












      18








      18


      11






      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?










      share|improve this question














      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Mar 18 '09 at 14:25









      Jeroen van DelftJeroen van Delft

      1381111




      1381111
























          11 Answers
          11






          active

          oldest

          votes


















          13














          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.






          share|improve this answer


























          • 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



















          9














          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.






          share|improve this answer

































            9














            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));
            }
            }





            share|improve this answer


























            • Exactly. JSON has no way of encoding what kind of object the original was.

              – Powerlord
              Mar 18 '09 at 14:33



















            3














            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.






            share|improve this answer































              2














              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






              share|improve this answer

































                1














                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.






                share|improve this answer
























                • 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



















                1














                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






                share|improve this answer
























                • 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



















                1














                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.






                share|improve this answer































                  0














                  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.






                  share|improve this answer































                    0














                    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)
                    }





                    share|improve this answer































                      -1














                      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 .)






                      share|improve this answer
























                      • 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











                      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
                      });


                      }
                      });














                      draft saved

                      draft discarded


















                      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









                      13














                      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.






                      share|improve this answer


























                      • 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
















                      13














                      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.






                      share|improve this answer


























                      • 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














                      13












                      13








                      13







                      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.






                      share|improve this answer















                      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.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      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



















                      • 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













                      9














                      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.






                      share|improve this answer






























                        9














                        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.






                        share|improve this answer




























                          9












                          9








                          9







                          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.






                          share|improve this answer















                          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.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited May 23 '17 at 11:33









                          Community

                          11




                          11










                          answered Mar 18 '09 at 15:06









                          Peter BaileyPeter Bailey

                          93.9k25165192




                          93.9k25165192























                              9














                              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));
                              }
                              }





                              share|improve this answer


























                              • Exactly. JSON has no way of encoding what kind of object the original was.

                                – Powerlord
                                Mar 18 '09 at 14:33
















                              9














                              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));
                              }
                              }





                              share|improve this answer


























                              • Exactly. JSON has no way of encoding what kind of object the original was.

                                – Powerlord
                                Mar 18 '09 at 14:33














                              9












                              9








                              9







                              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));
                              }
                              }





                              share|improve this answer















                              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));
                              }
                              }






                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              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



















                              • 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











                              3














                              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.






                              share|improve this answer




























                                3














                                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.






                                share|improve this answer


























                                  3












                                  3








                                  3







                                  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.






                                  share|improve this answer













                                  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.







                                  share|improve this answer












                                  share|improve this answer



                                  share|improve this answer










                                  answered Mar 18 '09 at 16:47









                                  boukebouke

                                  7,32354174




                                  7,32354174























                                      2














                                      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






                                      share|improve this answer






























                                        2














                                        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






                                        share|improve this answer




























                                          2












                                          2








                                          2







                                          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






                                          share|improve this answer















                                          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







                                          share|improve this answer














                                          share|improve this answer



                                          share|improve this answer








                                          edited May 23 '17 at 11:47









                                          Community

                                          11




                                          11










                                          answered Jul 16 '12 at 13:30









                                          mindplay.dkmindplay.dk

                                          4,99013240




                                          4,99013240























                                              1














                                              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.






                                              share|improve this answer
























                                              • 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
















                                              1














                                              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.






                                              share|improve this answer
























                                              • 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














                                              1












                                              1








                                              1







                                              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.






                                              share|improve this answer













                                              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.







                                              share|improve this answer












                                              share|improve this answer



                                              share|improve this answer










                                              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



















                                              • 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











                                              1














                                              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






                                              share|improve this answer
























                                              • 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
















                                              1














                                              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






                                              share|improve this answer
























                                              • 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














                                              1












                                              1








                                              1







                                              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






                                              share|improve this answer













                                              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







                                              share|improve this answer












                                              share|improve this answer



                                              share|improve this answer










                                              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



















                                              • 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











                                              1














                                              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.






                                              share|improve this answer




























                                                1














                                                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.






                                                share|improve this answer


























                                                  1












                                                  1








                                                  1







                                                  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.






                                                  share|improve this answer













                                                  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.







                                                  share|improve this answer












                                                  share|improve this answer



                                                  share|improve this answer










                                                  answered Oct 4 '16 at 13:55









                                                  Mihai RăducanuMihai Răducanu

                                                  3,34431625




                                                  3,34431625























                                                      0














                                                      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.






                                                      share|improve this answer




























                                                        0














                                                        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.






                                                        share|improve this answer


























                                                          0












                                                          0








                                                          0







                                                          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.






                                                          share|improve this answer













                                                          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.







                                                          share|improve this answer












                                                          share|improve this answer



                                                          share|improve this answer










                                                          answered Mar 18 '09 at 17:09









                                                          Alan StormAlan Storm

                                                          129k70330506




                                                          129k70330506























                                                              0














                                                              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)
                                                              }





                                                              share|improve this answer




























                                                                0














                                                                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)
                                                                }





                                                                share|improve this answer


























                                                                  0












                                                                  0








                                                                  0







                                                                  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)
                                                                  }





                                                                  share|improve this answer













                                                                  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)
                                                                  }






                                                                  share|improve this answer












                                                                  share|improve this answer



                                                                  share|improve this answer










                                                                  answered Nov 15 '18 at 2:17









                                                                  ryanbrainardryanbrainard

                                                                  4,7652338




                                                                  4,7652338























                                                                      -1














                                                                      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 .)






                                                                      share|improve this answer
























                                                                      • 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
















                                                                      -1














                                                                      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 .)






                                                                      share|improve this answer
























                                                                      • 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














                                                                      -1












                                                                      -1








                                                                      -1







                                                                      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 .)






                                                                      share|improve this answer













                                                                      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 .)







                                                                      share|improve this answer












                                                                      share|improve this answer



                                                                      share|improve this answer










                                                                      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



















                                                                      • 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


















                                                                      draft saved

                                                                      draft discarded




















































                                                                      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.




                                                                      draft saved


                                                                      draft discarded














                                                                      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





















































                                                                      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







                                                                      Popular posts from this blog

                                                                      Xamarin.iOS Cant Deploy on Iphone

                                                                      Glorious Revolution

                                                                      Dulmage-Mendelsohn matrix decomposition in Python