factory = $factory; $this->reader = $reader; } public function create($subject, array $groups = ['Default']) { return SerializationContext::create()->setSerializeNull(true)->setGroups($this->groups($subject, $groups)); } private function groups($subject, array $groups) { $metadata = $this->factory->getMetadataForClass(is_object($subject) ? get_class($subject) : $subject); $properties = $metadata instanceof ClassHierarchyMetadata ? collect($metadata->classMetadata)->flatMap(property('propertyMetadata')) : $metadata->propertyMetadata; $fields = []; /** @var PropertyMetadata $property */ foreach ($properties as $property) { try { $annotation = $this->getAnnotationForProperty($property); if ($annotation && !empty($fieldGroups = $this->map($annotation, $groups))) { $type = $property->type; $class = $type['name'] !== 'array' ? $type['name'] : $type['params'][0]; $fields[$property->name] = $this->groups($class, $fieldGroups); } } catch (\ReflectionException $e) { } } return array_merge($groups, $fields); } private function getAnnotationForProperty(PropertyMetadata $metadata) { $reflection = new \ReflectionClass($metadata->class); try { $property = $reflection->getProperty($metadata->name); /** @var SerializeAs $annotation */ return $this->reader->getPropertyAnnotation($property, SerializeAs::class); } catch (\ReflectionException $exception) { $method = $reflection->getMethod($metadata->getter); return $this->reader->getMethodAnnotation($method, SerializeAs::class); } } private function map(SerializeAs $annotation, array $groups) { $result = []; foreach ($groups as $group) { if (array_key_exists($group, $annotation->map)) { $result[] = $annotation->map[$group]; } else { $result[] = $groups; } } return $result; } }