Skip to content

Commit

Permalink
Support php7.4 nullable typed properties for JMS serializer.
Browse files Browse the repository at this point in the history
  • Loading branch information
zviryatko committed May 26, 2023
1 parent ebe6f59 commit c4cce49
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 0 deletions.
33 changes: 33 additions & 0 deletions ModelDescriber/JMSModelDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ public function describe(Model $model, OA\Schema $schema)
} catch (\ReflectionException $ignored) {
}
}
$this->checkRequiredFields($reflections, $schema, $name);
if (null !== $item->setter) {
try {
$reflections[] = new \ReflectionMethod($item->class, $item->setter);
Expand Down Expand Up @@ -346,4 +347,36 @@ private function propertyTypeUsesGroups(array $type)
return null;
}
}

/**
* Mark property as required if it is not nullable.
*
* @param array $reflections
* @param \OpenApi\Annotations\Schema $schema
* @param string $name
*/
public function checkRequiredFields(array $reflections, OA\Schema $schema, string $name): void
{
foreach ($reflections as $reflection) {
$nullable = false;
if ($reflection instanceof \ReflectionProperty) {
$type = PHP_VERSION_ID >= 70400 ? $reflection->getType() : null;
if (null !== $type && !$type->allowsNull()) {
$nullable = true;
}
} elseif ($reflection instanceof \ReflectionMethod) {
$returnType = $reflection->getReturnType();
if (null !== $returnType && !$returnType->allowsNull()) {
$nullable = true;
}
}
if ($nullable) {
$required = Generator::UNDEFINED !== $schema->required ? $schema->required : [];
$required[] = $name;

$schema->required = $required;
break;
}
}
}
}
13 changes: 13 additions & 0 deletions Tests/Functional/Controller/JMSController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSDualComplex;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSNamingStrategyConstraints;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSTyped;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSUser;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChat;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChatRoomUser;
Expand Down Expand Up @@ -136,4 +137,16 @@ public function minUserAction()
public function minUserNestedAction()
{
}

/**
* @Route("/api/jms_typed", methods={"GET"})
* @OA\Response(
* response=200,
* description="Success",
* @Model(type=JMSTyped::class)
* )
*/
public function typedAction()
{
}
}
43 changes: 43 additions & 0 deletions Tests/Functional/Entity/JMSTyped.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Nelmio\ApiDocBundle\Tests\Functional\Entity;

use JMS\Serializer\Annotation as Serializer;
use Nelmio\ApiDocBundle\Annotation\Model;
use OpenApi\Annotations as OA;

class JMSTyped
{
/**
* @Serializer\Type("integer")
*/
private int $id;

/**
* @OA\Property(ref=@Model(type=JMSUser::class))
* @Serializer\SerializedName("user")
*/
private JMSUser $User;

/**
* @Serializer\Type("string")
*/
private ?string $name;

/**
* @Serializer\VirtualProperty
* @OA\Property(ref=@Model(type=JMSUser::class))
*/
public function getVirtualFriend(): JMSUser
{
}
}
22 changes: 22 additions & 0 deletions Tests/Functional/JMSFunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -339,4 +339,26 @@ protected static function createKernel(array $options = []): KernelInterface
{
return new TestKernel(TestKernel::USE_JMS);
}

public function testModelTypedDocumentation()
{
if (PHP_VERSION_ID < 70400) {
$this->markTestSkipped('PHP 7.4 required.');
}
$this->assertEquals([
'type' => 'object',
'properties' => [
'id' => ['type' => 'integer'],
'user' => ['$ref' => '#/components/schemas/JMSUser'],
'name' => ['type' => 'string'],
'virtual_friend' => ['$ref' => '#/components/schemas/JMSUser'],
],
'required' => [
'virtual_friend',
'id',
'user',
],
'schema' => 'JMSTyped',
], json_decode($this->getModel('JMSTyped')->toJson(), true));
}
}

0 comments on commit c4cce49

Please sign in to comment.