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

MaxDepth exclusion strategy #136

Closed
yoye opened this issue Jan 16, 2014 · 22 comments
Closed

MaxDepth exclusion strategy #136

yoye opened this issue Jan 16, 2014 · 22 comments
Labels

Comments

@yoye
Copy link

yoye commented Jan 16, 2014

It seem's that MaxDepth exclusion strategy does not work. At the moment in jms-serializer it can only be tested if metadata is an instance of PropertyMetadata

https://github.com/schmittjoh/serializer/blob/master/src/JMS/Serializer/Exclusion/DepthExclusionStrategy.php#L55

But Exclusion can only be defined in class annotation.

@willdurand
Copy link
Owner

cc @adrienbrault

@adrienbrault
Copy link
Contributor

Would you mind creating a test case or some code so that I better understand what does not work ?

The RelationPropertyMetadata ( https://github.com/willdurand/Hateoas/blob/master/src/Hateoas/Serializer/Metadata/RelationPropertyMetadata.php ) we use inherits from PropertyMetadata ... so I don't see why that'd be an issue.

@yoye
Copy link
Author

yoye commented Jan 17, 2014

Well i can give an exemple, on the first gist I only use jmsserializer and the output with maxDepth = 1 is what i expected:

https://gist.github.com/yoye/8470702

{
    "username": "foo",
    "friend": {
        "username": "bar"
    }
}

But with hateoas lib i've got the following result:

https://gist.github.com/yoye/8470772

{
    "username": "foo",
    "_embedded": {
        "friend": {
            "username": "bar",
            "_embedded": {
                "friend": {
                    "username": "foobar",
                    "_embedded": {
                        "friend": {
                            "username": "baz",
                            "_embedded": {
                                "friend": null
                            }
                        }
                    }
                }
            }
        }
    }
}

Did I misunderstand MaxDepth usage ?

@willdurand
Copy link
Owner

So what is the status of this issue? ping @adrienbrault

@adrienbrault
Copy link
Contributor

There seems to be an issue, because the max depth exclusion strategy uses the serialization context stack, but the embedded objects metadata never get into the stack.

@hgraca
Copy link

hgraca commented Apr 25, 2014

Hi, I just stumbled upon this problem.

What is the status of this issue?

adrienbrault added a commit to adrienbrault/Hateoas that referenced this issue Apr 26, 2014
@adrienbrault
Copy link
Contributor

I've prototyped adrienbrault@1dd946b which fixes the issue in your example. However that's breaking tests and that has a very bad design.

I'm trying to see what I can do.

adrienbrault added a commit to adrienbrault/Hateoas that referenced this issue Apr 26, 2014
@adrienbrault
Copy link
Contributor

A slightly better architecture adrienbrault@85824b4

I will see what I can change on the serializer to make this implementation easier/cleaner.

@mhert
Copy link

mhert commented Jul 28, 2014

This problem affects me too. Could you say if you already have a solution?

@serhiikushch
Copy link

@adrienbrault, could you tell us what is the status of the bug?

@wodka
Copy link

wodka commented Feb 2, 2015

Any news here?

@mhert
Copy link

mhert commented Feb 5, 2015

@wodka I don't think it will ever be fixed. We will try to migrate away from this lib soon.

@wodka
Copy link

wodka commented Feb 5, 2015

@mhert you know an alternative or a fork where this has been fixed?

@mhert
Copy link

mhert commented Feb 5, 2015

@wodka Unfortunately not

@willdurand
Copy link
Owner

Did you try this patch? adrienbrault@85824b4

wodka added a commit to wodka/Hateoas that referenced this issue Feb 6, 2015
@wodka
Copy link

wodka commented Feb 6, 2015

I tried just now (just applied the changes to the current master)
in HateoasBundle/Resources/config/serializer.xml added the following to hateoas.event_subscriber.*

<call method="setMetadataFactory">
    <argument type="service" id="jms_serializer.metadata_factory" />
</call>

Sadly it now just stops at already serialized elements - it completely ignores the maxDepth setting.

@wodka
Copy link

wodka commented Feb 6, 2015

ok, I missed one thing:

if using FOSRestBundle it is required in annotation:

@Rest\View(serializerEnableMaxDepthChecks=true)

further the Exclusion has to be defined inside the Embedded annotation and not in the Relation annotation.

 * @Hateoas\Relation(
 *     name = "subelements",
 *     embedded = @Hateoas\Embedded(
 *         "expr(object.getSubelements())",
 *         exclusion = @Hateoas\Exclusion(maxDepth = 2)
 *     )
 * )

After moving the Metadata push before the embedded / link creation it seems to work. :)

to try:

in composer override the repositories:

{ "type": "vcs", "url":"https://github.com/wodka/Hateoas" },
{ "type": "vcs", "url": "https://github.com/wodka/BazingaHateoasBundle" }

and force the master branch:

"willdurand/hateoas": "dev-master",
"willdurand/hateoas-bundle": "dev-master",

If this is working for others as well - I'd create a pull request.

@neiron486k
Copy link

Don't work for me

@igormukhingmailcom
Copy link

@neiron486k Hi. This work, just checked.

This you should add to your controller:
@Rest\View(serializerEnableMaxDepthChecks=true)

This you should add to your entity:

 * @Hateoas\Relation(
 *     name = "subelements",
 *     embedded = @Hateoas\Embedded(
 *         "expr(object.getSubelements())",
 *         exclusion = @Hateoas\Exclusion(maxDepth = 2)
 *     )
 * )

One of my problems was that I've added exclusion not into embedded, but after it like this (next example is not working):

* @Hateoas\Relation(
 *     name = "subelements",
 *     embedded = @Hateoas\Embedded(
 *         "expr(object.getSubelements())"
 *     ),
 *    exclusion = @Hateoas\Exclusion(maxDepth = 2) <----- This should not be here
 * )

So maybe you have same issue. Read docs one more time - this helped me :)

@lchrusciel
Copy link

Hi everyone.
Same problem occurred during Sylius development when we started testing our API. We have few classes tightly coupled together and I am not able to define bidirectional relation between them. Just for example, let me present to you our case with User - Customer relation. Our Customer has User as one of its properties, and User has Customer. The problem which I have, is to present list of customers with users connected. I wasn't able to define such a configuration, which would allow for that. My current solution is to have one-directional relation from Customer to User, but I would prefer to allow User to be serialized with embedded Customer too. Our current serializer configuration looks like this:

  • Customer serialization:
Sylius\Component\User\Model\Customer:
    exclusion_policy: ALL
    xml_root_name: sylius_customer
    properties:
        id:
            expose: true
            type: integer
            groups: [Default, Detailed]
        email:
            expose: true
            type: string
            groups: [Detailed]
        emailCanonical:
            expose: true
            type: string
            groups: [Default, Detailed]
        firstName:
            expose: true
            type: string
            groups: [Default, Detailed]
        lastName:
            expose: true
            type: string
            groups: [Default, Detailed]
        gender:
            expose: true
            type: string
            groups: [Detailed]
        birthday:
            expose: true
            type: DateTime
            groups: [Detailed]
        groups:
            expose: true
            type: array
            groups: [Detailed]
    relations:
        - rel: user
          href:
              route: sylius_api_user_show
              parameters:
                  id: expr(object.getUser().getId())
          embedded:
              content: expr(object.getUser())
              xmlElementName: sylius_user
          exclusion:
              exclude_if: expr(object.getUser() === null)
  • User serialization:
Sylius\Component\User\Model\User:
    exclusion_policy: ALL
    xml_root_name: sylius_user
    properties:
        id:
            expose: true
            type: integer
            groups: [Default, Detailed]
        username:
            expose: true
            type: string
            groups: [Default, Detailed]
        usernameCanonical:
            expose: true
            type: string
            groups: [Detailed]
        enabled:
            expose: true
            type: boolean
            groups: [Default, Detailed]
        roles:
            expose: true
            type: array
            groups: [Detailed]

The configuration I thought would solve the problem looked like this:

  • Customer:
Sylius\Component\User\Model\Customer:
    exclusion_policy: ALL
    xml_root_name: sylius_customer
    properties:
        id:
            expose: true
            type: integer
            groups: [Default, Detailed]
        email:
            expose: true
            type: string
            groups: [Detailed]
        emailCanonical:
            expose: true
            type: string
            groups: [Default, Detailed]
        firstName:
            expose: true
            type: string
            groups: [Default, Detailed]
        lastName:
            expose: true
            type: string
            groups: [Default, Detailed]
        gender:
            expose: true
            type: string
            groups: [Detailed]
        birthday:
            expose: true
            type: DateTime
            groups: [Detailed]
        groups:
            expose: true
            type: array
            groups: [Detailed]
    relations:
        - rel: user
          href:
              route: sylius_api_user_show
              parameters:
                  id: expr(object.getUser().getId())
          embedded:
              content: expr(object.getUser())
              xmlElementName: sylius_user
              exclusion:
                  max_depth: 1
          exclusion:
              exclude_if: expr(object.getUser() === null)
  • User
Sylius\Component\User\Model\User:
    exclusion_policy: ALL
    xml_root_name: sylius_user
    properties:
        id:
            expose: true
            type: integer
            groups: [Default, Detailed]
        username:
            expose: true
            type: string
            groups: [Detailed]
        usernameCanonical:
            expose: true
            type: string
            groups: [Default, Detailed]
        enabled:
            expose: true
            type: boolean
            groups: [Default, Detailed]
        roles:
            expose: true
            type: array
            groups: [Detailed]
    relations:
        - rel: user
          href:
              route: sylius_api_customer_show
              parameters:
                  id: expr(object.getCustomer().getId())
          embedded:
              content: expr(object.getCustomer())
              xmlElementName: sylius_customer
              exclusion:
                max_depth: 1

Do you have any solution for that or any idea for some workaround?

@goetas
Copy link
Collaborator

goetas commented Apr 15, 2017

this should be solved with #246

@lchrusciel
Copy link

Thanks @goetas!

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

No branches or pull requests