Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embed objects and serialization groups #1001

Closed
Timherlaud opened this issue Mar 21, 2017 · 22 comments
Closed

Embed objects and serialization groups #1001

Timherlaud opened this issue Mar 21, 2017 · 22 comments
Assignees

Comments

@Timherlaud
Copy link

Hi,

I have a class Foo with field id and a parentId (which refer to a Foo object on ManyToOne) ,

itemOperations={
 *         "get"={"method"="GET", "normalization_context"={"groups"={"read"}}},
...
class Foo
{
  /**
   * @var int The id of this content
   *
   * @ORM\Id
   * @ORM\Column(type="guid")
   * @Assert\Uuid
   * @Groups({"read"})
   */
  private $id;

  ...
  * @Groups({"read"})
  private $name;

  /**
   * @var parentTranslateId[] The translate parent ID of this content
   *
   * @ORM\ManyToOne(targetEntity="Foo")
   * @Groups({"read"})
   */
  private $parentTranslateId;
}

If I want to add group on normalization context, the api result give me a Foo object embed to another Foo, or I want an IRI link

How to make serializer groups not recursive ?

@soyuka
Copy link
Member

soyuka commented Mar 21, 2017

Don't put a group on the ManyToOne relation. You can also use MaxDepth.

@Timherlaud
Copy link
Author

Hi @soyuka,

Thanks for your reply

I need groups because I have some fields to hide. Remove the group only hide the field but i need a IRI value.

MaxDepth is for object with multi level embed no ? For me it's at the first level of my main object, MaxDepth as no effect on my parentTranslate field.

@soyuka
Copy link
Member

soyuka commented Mar 21, 2017

Then you should use a second group for the relation.

itemOperations={
 *         "get"={"method"="GET", "normalization_context"={"groups"={"read", "read_child"}}},

   * @Groups({"read", "read_child"})
  private $id; //on id put the two groups

  //rest properties only `read` group

   * @ORM\ManyToOne(targetEntity="Foo")
   * @Groups({"read_child"})

Should do the trick I think

@Timherlaud
Copy link
Author

Timherlaud commented Mar 21, 2017

I have already try it but it doesn't work

@soyuka if you want try I make an exemple : https://github.com/Tim59/api-platform.git

just a fork of api platform with a simple Entity Foo. With 2 differents groups read and read_child, it does not work

@Timherlaud
Copy link
Author

Timherlaud commented Mar 22, 2017

Ping @soyuka , sorry but i'm on a big project and I think your solution to use different groups may work but there is a bug

@soyuka
Copy link
Member

soyuka commented Mar 22, 2017

@tim59 I'll take a look at your fork, were you able to reproduce the bug there?

@Timherlaud
Copy link
Author

@soyuka Thanks , Yes I have reproduce the bug on the fork

@soyuka soyuka self-assigned this Mar 22, 2017
@Timothe-Imadev
Copy link

Timothe-Imadev commented Mar 27, 2017

@soyuka have you time to try it ? thank's

@soyuka
Copy link
Member

soyuka commented Mar 27, 2017

So, indeed if I remove every groups I'm retrieving a simple string as id. Though, if there are groups, you'll get an object. I'm not sure that this should be considered as a bug or a feature.

May I ask why is it an issue to have an object instead of a string? Note that it won't get the full object back if the serialization group only uses the identifier.

ping @api-platform/core-team wdyt?

@jsamouh
Copy link
Contributor

jsamouh commented Mar 29, 2017

@soyuka , in fact , we have a very complex entity which refers to itself with a parent attribute.

If we let like this, when we do a get of this entity, API platform displays our complex structure json Entity including a complex structure json entity which is the parent attribute. Or we do not want to display the parent, only his IRI.

We use @groups to select only field we want to display, including the parent attribute. But of course, recursively, the normalizer displays the parent's attribute....

Need advice about this part ^^

@soyuka
Copy link
Member

soyuka commented Mar 29, 2017

@jordscream As the Entity is referencing itself, it seems logic (to me) that the groups apply recursively, and therefore you'll get every fields serialized by the root entity. It might be that you'd have to write your own normalizer for this use case, or maybe @teohhanhui has a better solution?

@soyuka
Copy link
Member

soyuka commented Mar 29, 2017

Maybe api-platform/docs#152 can be interesting.

@Timherlaud
Copy link
Author

@soyuka thank's but don't think that can help me, @dunglas or @teohhanhui any other ideas ?

@dunglas
Copy link
Member

dunglas commented Apr 3, 2017

I would use a custom normalizer storing the recursion level for such use case. I don't think we can use a generic solution for this.

@teohhanhui
Copy link
Contributor

teohhanhui commented May 25, 2017

Indeed I've tried to use max_depth and find it very limiting... At least there should be a way to normalize to IRI when max_depth is reached. And also max_depth 0 to indicate that we don't want to even recurse in (a.k.a. just serialize as IRI).

@oxan
Copy link
Contributor

oxan commented Jun 3, 2018

Once #1980 is fixed, this can be implemented as follows:

class Foo
{
  /**
   * @ORM\ManyToOne(targetEntity="Foo")
   * @Groups({"read"})
   * @ApiProperty(readableLink=false, writableLink=false)
   */
  private $parent;
}

which will generate an IRI for the parent instead of embedding it (this will work for any property to control embedding, not only for self-referencing properties).

In the mean time, you can workaround #1980 and achieve the same result by using something like this https://gist.github.com/oxan/5a9ba44e72bbeae5fa1aee7d0be0b337 and applying the @NotEmbedded annotation to the $parent property (this works for any property as well).

@essencious
Copy link

@oxan I am using the latest version of api-platform but setting @ApiProperty(readableLink=false, writableLink=false) doesn't seem to be doing anything. Any advice on this? Thanks

@oxan
Copy link
Contributor

oxan commented Oct 24, 2018

@essencious I don't think the fix for #1980 has actually landed in a released version yet.

@soyuka
Copy link
Member

soyuka commented Oct 24, 2018

f7b9079 it can't really be merged in 2.x because of #1997 (comment) :|

@essencious
Copy link

@soyuka @oxan thanks for your responses. I'll keep an eye out for future releases.

@vipulw2011
Copy link

Then you should use a second group for the relation.

itemOperations={
 *         "get"={"method"="GET", "normalization_context"={"groups"={"read", "read_child"}}},

   * @Groups({"read", "read_child"})
  private $id; //on id put the two groups

  //rest properties only `read` group

   * @ORM\ManyToOne(targetEntity="Foo")
   * @Groups({"read_child"})

Should do the trick I think

@soyuka How do I do the child group to get only few properties in same entity reference ?

soyuka pushed a commit to api-platform/docs that referenced this issue Aug 7, 2020
* Update serialization.md

Moves the "Calculated field" part outside the "Embedding relations" part.
Adds "Force IRI with relation of the same type" parts which describes the side effect of using serialization groups on a property of the same type of the current entity.
Adds the workaround using ApiProperty annotation described on the issue api-platform/core#1001 (comment) .

* Update serialization.md

Corrects spelling.
@do-web
Copy link

do-web commented Jun 5, 2021

Then you should use a second group for the relation.

itemOperations={
 *         "get"={"method"="GET", "normalization_context"={"groups"={"read", "read_child"}}},

   * @Groups({"read", "read_child"})
  private $id; //on id put the two groups

  //rest properties only `read` group

   * @ORM\ManyToOne(targetEntity="Foo")
   * @Groups({"read_child"})

Should do the trick I think

@soyuka How do I do the child group to get only few properties in same entity reference ?

Any news how to solve this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants