Comments (7)
Ah I see why this is happening at least. This happens because Member
class is used in both the ContactOutput
& EventOutput
. Both of these "output" classes get different serialization groups applied:
1.SerializationGroup::ContactOutputAll
, SerializationGroup::ContactAll
& SerializationGroup::MemberAll
2. SerializationGroup::EventOutputAll
, SerializationGroup::EventAll
& SerializationGroup::MemberAll
These groups also get passed to the child classes (the Member
class in this example). Technically speaking the different groups used could result in a different schema for the Member
class, which is the reason why you get a Member
& Member2
schema. It just so happens that both of these Schema's are the exact same. https://github.com/DjordyKoert/NelmioApiDocBundle/blob/52b297059b2ccf4bf1db3c8e80b5234f672fe4af/Tests/Functional/Fixtures/Issue2218.json#L216
You can see the setup that I used to replicate it in #2221. I am not yet sure what the proper way would be to change this behaviour or if this should stay as it is.
from nelmioapidocbundle.
Maybe creating an optional swagger-php processor which removes duplicate schemas is an option?
from nelmioapidocbundle.
I cannot seem to reproduce it. I do see a few typo's in your attributes though.
Incorrect Model
usage
new Model(Contact::class, groups: [SerializationGroup::ContactAll])
Should be
new Model(type: Contact::class, groups: [SerializationGroup::ContactAll])
Missing new on OA\Items
items: OA\Items(ref: new Model(Contact::class, groups: [SerializationGroup::ContactAll]))
Should be
items: new OA\Items(ref: new Model(type: Contact::class, groups: [SerializationGroup::ContactAll]))
from nelmioapidocbundle.
@DjordyKoert sorry for the mistakes, I made them without looking at the code, but this is not the problem I really have.
I'm going to start over, since it's harder to reproduce.
I have 3 entities: Member
, Contact
i Event
Member
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
#[ORM\Entity]
class Member
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
#[Serializer\Groups([SerializationGroup::MemberAll])]
private ?int $id = null;
// Other variables, constructor, getters and setters...
}
Contact
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
#[ORM\Entity]
class Contact
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
#[Serializer\Groups([SerializationGroup::ContactAll])]
private ?int $id = null;
#[ORM\ManyToOne(targetEntity: Member::class)]
#[Serializer\Ignore]
private Member $member;
// Other variables, constructor, getters and setters...
}
Event
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
#[ORM\Entity]
class Event
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
#[Serializer\Groups([SerializationGroup::EventAll])]
private ?int $id = null;
#[ORM\ManyToOne(targetEntity: Member::class)]
#[Serializer\Ignore]
private Member $member;
// Other variables, constructor, getters and setters...
}
Now i create 2 Outputs
called ContactOutput
i EventOutput
with another serialization groups
ContactOutput
<?php
namespace App\Dto\Output;
use App\Entity\Contact;
use App\Entity\Member;
use App\Serialization\Groups\SerializationGroup;
use Symfony\Component\Serializer\Annotation as Serializer;
class ContactOutput
{
#[Serializer\Groups([SerializationGroup::ContactOutputAll])]
private readonly Contact $contact;
#[Serializer\Groups([SerializationGroup::ContactOutputAll])]
private readonly Member $member;
public function __construct(Contact $contact, Member $member)
{
$this->contact = $contact;
}
public function getContact(): Contact
{
return $this->contact;
}
public function getMember(): Member
{
return $this->member;
}
}
EventOutput
<?php
namespace App\Dto\Output;
use App\Entity\Event;
use App\Entity\Member;
use App\Serialization\Groups\SerializationGroup;
use Symfony\Component\Serializer\Annotation as Serializer;
class EventOutput
{
#[Serializer\Groups([SerializationGroup::EventOutputAll])]
private readonly Event $event;
#[Serializer\Groups([SerializationGroup::EventOutputAll])]
private readonly Member $member;
public function __construct(Event $event, Member $member)
{
$this->event = $event;
}
public function getEventt(): Event
{
return $this->event;
}
public function getMember(): Member
{
return $this->member;
}
}
Now I want to use this outputs on the contact and event controllers
<?php
namespace App\Controller;
use OpenApi\Attributes as OA;
class ContactController extends BaseController
{
#[OA\Response(
response: 200,
description: 'Success',
content: new OA\JsonContent(
type: 'array',
items: new OA\Items(ref: new Model(type: ContactOutput::class, groups: [
SerializationGroup::ContactOutputAll,
SerializationGroup::ContactAll,
SerializationGroup::MemberAll
]))
)
)]
#[Route(...)]
public function list(){}
#[OA\Response(
response: 200,
description: 'Success',
content: new OA\JsonContent(
ref: new Model(type: ContactOutput::class, groups: [
SerializationGroup::ContactOutputAll,
SerializationGroup::ContactAll,
SerializationGroup::MemberAll
])
)
)]
#[Route(...)]
public function show(){}
#[OA\Response(
response: 201,
description: 'Success',
content: new OA\JsonContent(
ref: new Model(type: ContactOutput::class, groups: [
SerializationGroup::ContactOutputAll,
SerializationGroup::ContactAll,
SerializationGroup::MemberAll
])
)
)]
#[Route(...)]
public function create(){}
#[OA\Response(
response: 200,
description: 'Success',
content: new OA\JsonContent(
ref: new Model(type: ContactOutput::class, groups: [
SerializationGroup::ContactOutputAll,
SerializationGroup::ContactAll,
SerializationGroup::MemberAll
])
)
)]
#[Route(...)]
public function update(){}
}
<?php
namespace App\Controller;
use OpenApi\Attributes as OA;
class EventController extends BaseController
{
#[OA\Response(
response: 200,
description: 'Success',
content: new OA\JsonContent(
type: 'array',
items: new OA\Items(ref: new Model(type: EventOutput::class, groups: [
SerializationGroup::EventOutputAll,
SerializationGroup::EventAll,
SerializationGroup::MemberAll
]))
)
)]
#[Route(...)]
public function list(){}
#[OA\Response(
response: 200,
description: 'Success',
content: new OA\JsonContent(
ref: new Model(type: EventOutput::class, groups: [
SerializationGroup::EventOutputAll,
SerializationGroup::EventAll,
SerializationGroup::MemberAll
])
)
)]
#[Route(...)]
public function show(){}
#[OA\Response(
response: 201,
description: 'Success',
content: new OA\JsonContent(
ref: new Model(type: EventOutput::class, groups: [
SerializationGroup::EventOutputAll,
SerializationGroup::EventAll,
SerializationGroup::MemberAll
])
)
)]
#[Route(...)]
public function create(){}
#[OA\Response(
response: 200,
description: 'Success',
content: new OA\JsonContent(
ref: new Model(type: EventOutput::class, groups: [
SerializationGroup::EventOutputAll,
SerializationGroup::EventAll,
SerializationGroup::MemberAll
])
)
)]
#[Route(...)]
public function update(){}
}
Now in schemas there's a duplicated schemas
from nelmioapidocbundle.
I have been dealing with the same issue- also using a response object to wraps my entities. I just assumed it was just incorrect usage somewhere else on my end. Coincidentally, this was the root cause for me writing up #2099
from nelmioapidocbundle.
@DjordyKoert Same issue on my side.
from nelmioapidocbundle.
@DjordyKoert Maybe an approach would be to only consider the groups that actually affect the model for creating the hash, and therefore unique models.
In the example above, even though we are using 3 groups, the Contact
submodel is actually only affected by one of them.
Of course we still need to keep track of the root groups for nested models down the serialization tree.
I tried to look at the code, but it won't be an easy task and sadly now I don't have the time :(
from nelmioapidocbundle.
Related Issues (20)
- Required field in OpenAPI response HOT 1
- Error with Model Attribute HOT 6
- @OA\Items() is required when @OA\Property HOT 7
- [Bug]: Swagger assets ignore X-Forwarded-Prefix header value HOT 2
- [Question]: DocumentExtension not getting loaded in Test context HOT 3
- [Bug]: 'Type' Expected, given string when using 'ref: new Model(type: Entity::class)' in attribute HOT 2
- incorrect server url in openapi document when behind reverse proxy HOT 1
- [Bug]: Not all integer range types supported HOT 3
- [Bug]: Object of class Nelmio\ApiDocBundle\Annotation\Model could not be converted to string HOT 4
- [Bug]: Assert\NotBlank is considered regardless of it's group values HOT 1
- [Question]: Discriminator schema with Doctrine ORM Discriminator map HOT 2
- [Feature]: Webhook support
- [RFC]: Adopt Conventional Commits HOT 1
- [Question]: Is it possible to view a web form when mediaType is "application/json"? HOT 2
- [Feature]: FOSRestBundle QueryParam AND nelmio_api_doc.yaml
- [Feature]: FOSRestBundle QueryParam AND nelmio_api_doc.yaml
- [Bug]: @OA\Property excludes property from model's required array HOT 2
- [Bug]: Lost data format in schema for array of objects HOT 1
- [Feature]: Describing default error response
- [Question]: Code breaks after updating from 4.25.2 to 4.25.3 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nelmioapidocbundle.