public function construct(VisitorInterface $visitor, ClassMetadata $metadata, $data, Type $type, DeserializationContext $context) { if (!$type->is(BlogPost::class)) { return parent::construct($visitor, $metadata, $data, $type, $context); } return new BlogPost('This is a nice title.', new Author('Foo Bar'), new \DateTime('2011-07-30 00:00', new \DateTimeZone('UTC')), new Publisher('Bar Foo')); }
protected function getElementType(Type $type) { if (0 === $type->countParams()) { return null; } $params = $type->getParams(); if (isset($params[1]) && $params[1] instanceof Type) { return $params[1]; } return $params[0]; }
public function testFromArray() { $data = ['cost' => ['price' => 2.5]]; $expected = new Order(new Price(2.5)); $result = $this->serializer->fromArray($data, Type::from(Order::class)); $this->assertEquals($expected, $result); }
public function testDoesNotRewriteCustomType() { $event = $this->createEvent($obj = new SimpleObjectProxy('a', 'b'), Type::from('FakedName')); $this->subscriber->onPreSerialize($event); $this->assertEquals(Type::from('FakedName'), $event->getType()); $this->assertTrue($obj->__isInitialized()); }
public function testBlogPostCaseInsensitive() { $m = new ClassMetadata(new \ReflectionClass('Kcs\\Serializer\\Tests\\Fixtures\\BlogPost')); $this->getLoaderForSubDir('case')->loadClassMetadata($m); $p = new PropertyMetadata($m->getName(), 'title'); $p->type = Type::from('string'); $this->assertEquals($p, $m->getAttributeMetadata('title')); }
public function visitArray($data, Type $type, Context $context) { if (!is_array($data)) { throw new RuntimeException(sprintf('Expected array, but got %s: %s', gettype($data), json_encode($data))); } // If no further parameters were given, keys/values are just passed as is. if (!$type->hasParam(0)) { $this->setData($data); return $data; } switch ($type->countParams()) { case 1: // Array is a list. $listType = $type->getParam(0); $result = []; foreach ($data as $v) { $result[] = $context->accept($v, $listType); } $this->setData($result); return $result; case 2: // Array is a map. $keyType = $type->getParam(0); $entryType = $type->getParam(1); $result = []; foreach ($data as $k => $v) { $result[$context->accept($k, $keyType)] = $context->accept($v, $entryType); } $this->setData($result); return $result; default: throw new RuntimeException(sprintf('Array type cannot have more than 2 parameters, but got %s.', json_encode($type->getParams()))); } }
public function testAccessorAttributes() { $m = new ClassMetadata(new \ReflectionClass('Kcs\\Serializer\\Tests\\Fixtures\\GetSetObject')); $this->getLoader()->loadClassMetadata($m); $p = new PropertyMetadata($m->getName(), 'name'); $p->type = Type::from('string'); $p->getter = 'getTrimmedName'; $p->setter = 'setCapitalizedName'; $this->assertEquals($p, $m->getAttributeMetadata('name')); }
public function testBuildWithoutAnythingElse() { $serializer = $this->builder->build(); $this->assertEquals('"foo"', $serializer->serialize('foo', 'json')); $this->assertEquals('<?xml version="1.0" encoding="UTF-8"?> <result><![CDATA[foo]]></result> ', $serializer->serialize('foo', 'xml')); $this->assertEquals('foo ', $serializer->serialize('foo', 'yml')); $this->assertEquals('foo', $serializer->deserialize('"foo"', Type::from('string'), 'json')); $this->assertEquals('foo', $serializer->deserialize('<?xml version="1.0" encoding="UTF-8"?><result><![CDATA[foo]]></result>', Type::from('string'), 'xml')); }
} return $post; } $serializer = \Kcs\Serializer\SerializerBuilder::create()->setEventDispatcher(new \Symfony\Component\EventDispatcher\EventDispatcher())->build(); $collection = createCollection(); $metrics = []; $f = function ($format) use($serializer, $collection) { $serializer->serialize($collection, $format); }; // Load all necessary classes into memory. $f('array'); $table = new \Symfony\Component\Console\Helper\Table($output); $table->setHeaders(['Format', 'Direction', 'Time']); $progressBar = new \Symfony\Component\Console\Helper\ProgressBar($output, 8); $progressBar->start(); foreach (['array', 'json', 'yml', 'xml'] as $format) { $table->addRow([$format, 'serialize', benchmark($f, $format)]); $progressBar->advance(); } $serialized = ['array' => $serializer->serialize($collection, 'array'), 'json' => $serializer->serialize($collection, 'json'), 'yml' => $serializer->serialize($collection, 'yml'), 'xml' => $serializer->serialize($collection, 'xml')]; $type = new \Kcs\Serializer\Type\Type('array', [\Kcs\Serializer\Type\Type::from(\Kcs\Serializer\Tests\Fixtures\BlogPost::class)]); $d = function ($format) use($serializer, $serialized, $type) { $serializer->deserialize($serialized[$format], $type, $format); }; foreach (['array', 'json', 'yml', 'xml'] as $format) { $table->addRow([$format, 'deserialize', benchmark($d, $format)]); $progressBar->advance(); } $progressBar->finish(); $progressBar->clear(); $table->render();
private function visitArray(VisitorInterface $visitor, $data, Type $type, $context) { if ($context instanceof SerializationContext && $type->hasParam(0) && !$type->hasParam(1)) { $data = array_values($data); } return $visitor->visitArray($data, $type, $context); }
public function setType($type) { $this->type = Type::parse($type); }
public function visitDouble($data, Type $type, Context $context) { if ($this->isNullNode($data)) { return $this->visitNull(null, Type::null(), $context); } return parent::visitDouble($data, $type, $context); }
public function testXmlNamespaceInheritanceMetadata() { $m = new ClassMetadata(new \ReflectionClass(SimpleClassObject::class)); $this->getLoader()->loadClassMetadata($m); $this->assertNotNull($m); $this->assertCount(3, $m->xmlNamespaces); $this->assertArrayHasKey('old_foo', $m->xmlNamespaces); $this->assertEquals('http://old.foo.example.org', $m->xmlNamespaces['old_foo']); $this->assertArrayHasKey('foo', $m->xmlNamespaces); $this->assertEquals('http://foo.example.org', $m->xmlNamespaces['foo']); $this->assertArrayHasKey('new_foo', $m->xmlNamespaces); $this->assertEquals('http://new.foo.example.org', $m->xmlNamespaces['new_foo']); $this->assertCount(3, $m->getAttributesMetadata()); $p = new PropertyMetadata($m->getName(), 'foo'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://old.foo.example.org'; $p->xmlAttribute = true; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $m->getAttributeMetadata('foo')); $p = new PropertyMetadata($m->getName(), 'bar'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://foo.example.org'; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $m->getAttributeMetadata('bar')); $p = new PropertyMetadata($m->getName(), 'moo'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://new.foo.example.org'; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $m->getAttributeMetadata('moo')); $subm = new ClassMetadata(new \ReflectionClass(SimpleSubClassObject::class)); $this->getLoader()->loadClassMetadata($subm); $this->assertNotNull($subm); $this->assertCount(2, $subm->xmlNamespaces); $this->assertArrayHasKey('old_foo', $subm->xmlNamespaces); $this->assertEquals('http://foo.example.org', $subm->xmlNamespaces['old_foo']); $this->assertArrayHasKey('foo', $subm->xmlNamespaces); $this->assertEquals('http://better.foo.example.org', $subm->xmlNamespaces['foo']); $this->assertCount(3, $subm->getAttributesMetadata()); $p = new PropertyMetadata($subm->getName(), 'moo'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://better.foo.example.org'; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $subm->getAttributeMetadata('moo')); $p = new PropertyMetadata($subm->getName(), 'baz'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://foo.example.org'; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $subm->getAttributeMetadata('baz')); $p = new PropertyMetadata($subm->getName(), 'qux'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://new.foo.example.org'; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $subm->getAttributeMetadata('qux')); $subm->merge($m); $this->assertNotNull($subm); $this->assertCount(3, $subm->xmlNamespaces); $this->assertArrayHasKey('old_foo', $subm->xmlNamespaces); $this->assertEquals('http://foo.example.org', $subm->xmlNamespaces['old_foo']); $this->assertArrayHasKey('foo', $subm->xmlNamespaces); $this->assertEquals('http://better.foo.example.org', $subm->xmlNamespaces['foo']); $this->assertArrayHasKey('new_foo', $subm->xmlNamespaces); $this->assertEquals('http://new.foo.example.org', $subm->xmlNamespaces['new_foo']); $this->assertCount(5, $subm->getAttributesMetadata()); $p = new PropertyMetadata($subm->getName(), 'moo'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://better.foo.example.org'; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $subm->getAttributeMetadata('moo')); $p = new PropertyMetadata($subm->getName(), 'baz'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://foo.example.org'; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $subm->getAttributeMetadata('baz')); $p = new PropertyMetadata($subm->getName(), 'qux'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://new.foo.example.org'; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $subm->getAttributeMetadata('qux')); if (defined('HHVM_VERSION')) { $this->markTestSkipped('This test executes partially in HHVM due to wrong class reported in PropertyMetadata'); return; } $p = new PropertyMetadata($subm->getName(), 'foo'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://old.foo.example.org'; $p->xmlAttribute = true; $p->class = 'Kcs\\Serializer\\Tests\\Fixtures\\SimpleClassObject'; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $subm->getAttributeMetadata('foo')); $p = new PropertyMetadata($subm->getName(), 'bar'); $p->type = Type::from('string'); $p->xmlNamespace = 'http://foo.example.org'; $p->class = 'Kcs\\Serializer\\Tests\\Fixtures\\SimpleClassObject'; $p->accessorType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $this->assertEquals($p, $subm->getAttributeMetadata('bar')); }
/** * @return string * @param Type $type */ private function getFormat(Type $type) { return $type->hasParam(0) ? $type->getParam(0) : $this->defaultFormat; }
public function getTypes() { $types = [['string', Type::from('string')], ['array<Foo>', new Type('array', [Type::from('Foo')])], ['array<Foo,Bar>', new Type('array', [Type::from('Foo'), Type::from('Bar')])], ['array<Foo\\Bar, Baz\\Boo>', new Type('array', [Type::from('Foo\\Bar'), Type::from('Baz\\Boo')])], ['a<b<c,d>,e>', new Type('a', [new Type('b', [Type::from('c'), Type::from('d')]), Type::from('e')])], ['Foo', Type::from('Foo')], ['Foo\\Bar', Type::from('Foo\\Bar')], ['Foo<"asdf asdf">', new Type('Foo', ['asdf asdf'])]]; return $types; }
/** * @dataProvider getPrimitiveTypes */ public function testPrimitiveTypes($primitiveType, $data) { $visitor = $this->serializationVisitors['json']; $functionToCall = 'visit' . ucfirst($primitiveType); $result = $visitor->{$functionToCall}($data, Type::null(), $this->createMock(Context::class)); if ($primitiveType == 'double') { $primitiveType = 'float'; } $this->assertInternalType($primitiveType, $result); }
protected function setUp() { $loader = new AnnotationLoader(); $loader->setReader(new AnnotationReader()); $this->factory = new MetadataFactory($loader); $this->handlerRegistry = new HandlerRegistry(); $this->handlerRegistry->registerSubscribingHandler(new ConstraintViolationHandler()); $this->handlerRegistry->registerSubscribingHandler(new DateHandler()); $this->handlerRegistry->registerSubscribingHandler(new FormErrorHandler(new IdentityTranslator(new MessageSelector()))); $this->handlerRegistry->registerSubscribingHandler(new PhpCollectionHandler()); $this->handlerRegistry->registerSubscribingHandler(new ArrayCollectionHandler()); $this->handlerRegistry->registerHandler(Direction::DIRECTION_SERIALIZATION, 'AuthorList', function (VisitorInterface $visitor, $object, Type $type, Context $context) { return $visitor->visitArray(iterator_to_array($object), $type, $context); }); $this->handlerRegistry->registerHandler(Direction::DIRECTION_DESERIALIZATION, 'AuthorList', function (VisitorInterface $visitor, $data, $type, Context $context) { $type = new Type('array', [Type::from('integer'), Type::from(Author::class)]); $elements = $context->accept($data, $type); $list = new AuthorList(); foreach ($elements as $author) { $list->add($author); } return $list; }); $this->dispatcher = new EventDispatcher(); $this->dispatcher->addSubscriber(new DoctrineProxySubscriber()); $namingStrategy = new SerializedNameAnnotationStrategy(new CamelCaseNamingStrategy()); $objectConstructor = new UnserializeObjectConstructor(); $this->serializationVisitors = ['array' => new GenericSerializationVisitor($namingStrategy), 'json' => new JsonSerializationVisitor($namingStrategy), 'xml' => new XmlSerializationVisitor($namingStrategy), 'yml' => new YamlSerializationVisitor($namingStrategy)]; $this->deserializationVisitors = ['array' => new GenericDeserializationVisitor($namingStrategy), 'xml' => new XmlDeserializationVisitor($namingStrategy), 'yml' => new YamlDeserializationVisitor($namingStrategy), 'json' => new JsonDeserializationVisitor($namingStrategy)]; $this->serializer = new Serializer($this->factory, $this->handlerRegistry, $objectConstructor, $this->serializationVisitors, $this->deserializationVisitors, $this->dispatcher); }
public function testWhitelistedDocumentTypesAreAllowed() { $this->deserializationVisitors['xml']->setDoctypeWhitelist(['<!DOCTYPE authorized SYSTEM "http://authorized_url.dtd">', '<!DOCTYPE author [<!ENTITY foo SYSTEM "php://filter/read=convert.base64-encode/resource=' . basename(__FILE__) . '">]>']); $this->serializer->deserialize('<?xml version="1.0"?> <!DOCTYPE authorized SYSTEM "http://authorized_url.dtd"> <foo></foo>', Type::from('stdClass'), 'xml'); $this->serializer->deserialize('<?xml version="1.0"?> <!DOCTYPE author [ <!ENTITY foo SYSTEM "php://filter/read=convert.base64-encode/resource=' . basename(__FILE__) . '"> ]> <foo></foo>', Type::from('stdClass'), 'xml'); }