/**
  * Add separate flow for annotated data objects.
  *
  * @param \Magento\Framework\Webapi\ServiceOutputProcessor $subject
  * @param \Closure $proceed
  * @param $data
  * @param $type
  * @return mixed
  */
 public function aroundConvertValue(\Magento\Framework\Webapi\ServiceOutputProcessor $subject, \Closure $proceed, $data, $type)
 {
     if ($data instanceof \Flancer32\Lib\DataObject) {
         $result = [];
         $typeData = $this->_typePropertiesRegistry->register($type);
         /**
          * @var string $propertyName
          * @var \Praxigento\Core\Reflection\Data\Property $propertyData
          */
         foreach ($typeData as $propertyName => $propertyData) {
             $attrName = $this->_toolConvert->camelCaseToSnakeCase($propertyName);
             $getter = 'get' . ucfirst($propertyName);
             $value = call_user_func([$data, $getter]);
             $isRequired = $propertyData->getIsRequired();
             $propertyType = $propertyData->getType();
             if ($isRequired || $value) {
                 if ($this->_toolType->isSimple($propertyType)) {
                     $result[$attrName] = $value;
                 } else {
                     // the last 2 chars will be removed for arrays
                     // in \Magento\Framework\Webapi\ServiceOutputProcessor::convertValue
                     if (is_array($value)) {
                         $propertyType = $this->_toolType->getTypeAsArrayOfTypes($propertyType);
                     }
                     $result[$attrName] = $proceed($value, $propertyType);
                 }
             }
         }
     } else {
         $result = $proceed($data, $type);
     }
     return $result;
 }
 public function test_getTypeAsArrayOfTypes()
 {
     /** === Test Data === */
     $TYPE = 'SomeType';
     $TYPE_ARR = 'SomeType[]';
     /** === Call and asserts  === */
     $res = $this->obj->getTypeAsArrayOfTypes($TYPE);
     $this->assertEquals($TYPE_ARR, $res);
 }
 /**
  * @param string $type
  * @param array $data
  * @return DataObject|mixed
  */
 public function parseArrayData($type, $data)
 {
     $isArray = $this->_toolType->isArray($type);
     $typeNorm = $this->_toolType->normalizeType($type);
     if (is_subclass_of($typeNorm, \Flancer32\Lib\DataObject::class)) {
         /* Process data objects separately. Register annotated class and parse parameters types. */
         if ($isArray) {
             /* process $data as array of $types */
             $result = [];
             foreach ($data as $key => $item) {
                 $result[$key] = $this->parseArrayDataRecursive($typeNorm, $item);
             }
         } else {
             /* process $data as data object of $type */
             $typeData = $this->_typePropsRegistry->register($typeNorm);
             $result = $this->_manObj->create($typeNorm);
             foreach ($data as $key => $value) {
                 $propName = $this->_toolType->formatPropertyName($key);
                 if (isset($typeData[$propName])) {
                     /** @var \\Praxigento\Core\Reflection\Data\Property $propertyData */
                     $propertyData = $typeData[$propName];
                     $propertyType = $propertyData->getType();
                     $propertyIsArray = $propertyData->getIsArray();
                     if ($propertyIsArray) {
                         /* property is the array of types */
                         $propertyType = $this->_toolType->getTypeAsArrayOfTypes($propertyType);
                         $complex = $this->parseArrayDataRecursive($propertyType, $value);
                         $result->setData($propName, $complex);
                     } else {
                         if ($this->_toolType->isSimple($propertyType)) {
                             /* property is the simple type */
                             $result->setData($propName, $value);
                         } else {
                             /* property is the complex type, we need to convert recursively */
                             $complex = $this->parseArrayDataRecursive($propertyType, $value);
                             $result->setData($propName, $complex);
                         }
                     }
                 }
             }
         }
     } else {
         $result = $data;
     }
     return $result;
 }