/**
  * @param object $object object instance to traverse
  *
  * @throws \InvalidArgumentException
  *
  * @return array
  */
 public function createArray($object)
 {
     if (!is_object($object)) {
         throw new \InvalidArgumentException('The first param should be a object.');
     }
     $array = [];
     if ($object instanceof Object2ArrayInterface) {
         $array = $object->__toArray();
         array_walk_recursive($array, function (&$item) {
             if (is_object($item)) {
                 $item = $this->createArray($item);
             }
         });
     } else {
         $reflClass = new \ReflectionClass($object);
         foreach (Utils::getClassProperties($reflClass) as $property) {
             if ($this->context->getReader()->isReadable($object, $property->getName())) {
                 $value = $this->context->getReader()->getValue($object, $property->getName());
                 $types = $types = Utils::getPropertyTypes($property);
                 $value = $this->parseValue($value, $types, $property, $object);
                 if ($value === null && $this->context->isIgnoreNulls()) {
                     continue;
                 }
                 $transformedName = $this->context->getNamingStrategy()->transformName($property->getName());
                 $array[$transformedName] = $value;
             }
         }
     }
     return $array;
 }
 /**
  * @param object $object object instance to populate
  * @param array  $data   array of data to apply
  *
  * @throws \InvalidArgumentException
  */
 public function populate($object, array $data)
 {
     if (!is_object($object)) {
         throw new \InvalidArgumentException('The first param should be a object.');
     }
     if ($object instanceof Array2ObjectInterface) {
         $object->__populate($data);
     } else {
         $reflClass = new \ReflectionClass($object);
         foreach (Utils::getClassProperties($reflClass) as $property) {
             foreach ($data as $key => $value) {
                 if ($this->context->getMatcher()->match($property, $key) && $this->context->getWriter()->isWritable($object, $property->getName())) {
                     $types = Utils::getPropertyTypes($property);
                     $value = $this->parseValue($value, $types, $property, $object);
                     $this->context->getWriter()->setValue($object, $property->getName(), $value);
                 }
             }
         }
     }
 }