Nelmioapidocbundle: Nelmio's information extraction strategy

Created on 18 Mar 2020  路  4Comments  路  Source: nelmio/NelmioApiDocBundle

Hi guys,

During my migration from Symfone 3.4 to 4.4 on several projects, I dropped JMS Serializer to use the Symfony's one. One of the key feature was the support of SerializedName which is very handy. But I noticed that Nelmio does some weird stuff when it comes to extract the API information from a method. It seems that it does not take into account the @SWG\Property that I put on the method neither the @SerializedName that I provided.

I may have missed something but when I look at the code, it seems that in the ObjectModelDescriber, Nelmio first extracts all properties and then try to work with it. This is not very efficient because when @SerializedName is used, some methods or properties can share the same serialized name without the same serialization group.

Why does ObjectModelDescriber use this way of extracting the information where it can get the ReflectionProperty or ReflectionMethod of the serialization groups present in the context, try to extract the @SWG\Property and if does not exist, THEN try to extract the information from the various information present from the PHPDoc?

Thanks for your answer :) This behaviour really blocks me right now and I would be glad to figure this out! I'll work by my side to find a small and quick fix/workaround.

EDIT: Here is the one of the use cases I get

  • From the Controller:
/**
 * Rest\Get("/my-route")
 *
 * @SWG\Response(
 *     response="200",
 *     description="Returned when successful",
 *     @SWG\Schema(
 *         type="array",
 *         @SWG\Items(ref=@Nelmio\Model(
 *              type=App\Entity\Domain::class,
 *              groups={
 *                  "domain_children_ids",
 *                  "domain_id",
 *                  "domain_name",
 *              }
 *          ))
 *      )
 * )
 */
public function getDomain(): Response
{ 
    //...
}

From the Entity:

class Domain 
{
    //...

   /**
    * @SerializedName("children")
    * @Groups("domain_children_ids")
    *
    * @SWG\Property(property="children", type="array", description="Subdomains of the domain",
    *     @SWG\Items(
    *          type="object",
    *          @SWG\Property(property="id", type="integer")
    *     )
    * )
    *
    * @return array|object
    */
    public function getSubdomainsId(): array
    {
        $result = [];

        foreach ($this->children as $child) {
            $result[] = ['id' => $child->getId()];
        }

        return $result;
    }
}

Most helpful comment

See https://github.com/nelmio/NelmioApiDocBundle/pull/1636 for the support of @SerializedName

All 4 comments

Hi! Sorry for the late reply...
About the @SerializedName annotations, we would need to take into account the Serializer's name converter, this is completely doable, just wasn't done yet. PR welcome :)

About taking into account @Property on methods, this is a bit more complex as it would force us to copy some of the logic used by the serializer to find the correspondance between methods and properties.
A workaround is adding a @Schema to your class:
```
/**

  • @SWG\Schema(
  • @SWG\Property(property="children", type="array", description="Subdomains of the domain",
  • @SWG\Items(
  • type="object",
  • @SWG\Property(property="id", type="integer")
  • )
  • )
  • )
    */
    class Domain
    {
    //...

/**
* @SerializedName("children")
* @Groups("domain_children_ids")
*
* @return array|object
*/
public function getSubdomainsId(): array
{
$result = [];

    foreach ($this->children as $child) {
        $result[] = ['id' => $child->getId()];
    }

    return $result;
}

}
```

Would that be acceptable?

See https://github.com/nelmio/NelmioApiDocBundle/pull/1636 for the support of @SerializedName

Thanks a lot :) That is a really good news!

The issue with the Schema but in the class annotation is that if you have multiple methods that can be serialized with the same name (SerializedName) but will not return the same object, it is impossible to describes per methods.

As there is SymfonyConstraintAnnotationReader, do you know if it is possible somehow to get the property or method attached to a property name rather than only the property? Maybe there is a tool in Symfony's Property Access component?

I'll dig a bit whenever I can find some time to do it :)

The issue with the Schema but in the class annotation is that if you have multiple methods that can be serialized with the same name (SerializedName) but will not return the same object, it is impossible to describes per methods.

This should be fixed by https://github.com/nelmio/NelmioApiDocBundle/pull/1678 :)
Please try it and tell me if you notice any unwanted behavior.

As there is SymfonyConstraintAnnotationReader, do you know if it is possible somehow to get the property or method attached to a property name rather than only the property? Maybe there is a tool in Symfony's Property Access component?

Unfortunately we can't rely on a component from Symfony to do this (methods listing is internal), though we detect methods similarly: https://github.com/nelmio/NelmioApiDocBundle/pull/1678/files#diff-fcb527927760cd4ec2bad6293b96665dR112-R130

Was this page helpful?
0 / 5 - 0 ratings

Related issues

astronati picture astronati  路  3Comments

Gemorroj picture Gemorroj  路  6Comments

alxfv picture alxfv  路  5Comments

kojidev picture kojidev  路  6Comments

andydandy80 picture andydandy80  路  4Comments