Serializer Annotations

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Serializer Annotations

Alright, now let me show you one other powerful thing about the serializer. The control you have over your objects! By default, it serializes all of your properties. But let’s say we don’t want the userId to be serialized. After all this isn’t really an important field for the API, it’s just the id of the user that created the programmer.

To start, open up the feature file and add a line to test that this property isn’t in the response:

# features/api/programmer.feature
# ...

Scenario: GET one programmer
  Given the following programmers exist:
    | nickname   | avatarNumber |
    | UnitTester | 3            |
  When I request "GET /api/programmers/UnitTester"
  # ...
  And the "userId" property should not exist

We’re using a custom Behat context that I created for this project with a lot of these nice sentences. To see a list of all of them, you can run behat with the -dl option, which stands for “definition list”:

php vendor/bin/behat -dl

Try running the tests again. It should fail, and it does - saying that the userId property should not exist, but we can see that it in fact is there.

Configuring the Serializer with Annotations

As soon as you want to take control over what properties are returned, we’re going to use annotations. Let’s look at their documentation first and find the Annotation Reference section - this is by far the most interesting page. The first item on the list is what we need, but there’s a huge list of annotations that give you all sorts of control.

Remember, whenever you use an annotation, you need a use statement for it. PHPStorm is tagging in to help me auto-complete the ExclusionPolicy class. Then I’ll remove the last part and alias this to Serializer. This will allow us to use any of the JMS serializer annotations by starting with @Serializer:

// src/KnpU/CodeBattle/Model/Programmer.php
// ...

/**
 * @Serializer\ExclusionPolicy("all")
 */
class Programmer
{
    // ...
}

For example, on top of the class, we can say @Serializer\ExclusionPolicy("all"). We’ve now told the serializer to not serialize any of the properties in this class, unless we tell it to specifically. Whereas before, it was serializing everything.

To actually include things, we whitelist them with the @Serializer\Expose annotation. I’ll copy this and use it on nickname, avatarNumber, tagLine and powerLevel fields:

// src/KnpU/CodeBattle/Model/Programmer.php
// ...

/**
 * @Serializer\ExclusionPolicy("all")
 */
class Programmer
{
    // ...

    public $id;

    /**
     * @Serializer\Expose
     */
    public $nickname;

    /**
     * @Serializer\Expose
     */
    public $avatarNumber;

    /**
     * @Serializer\Expose
     */
    public $tagLine;

    public $userId;

    /**
     * @Serializer\Expose
     */
    public $powerLevel = 0;
}

This is just one of the customizations you can make with annotations.

Now let’s re-run the test:

php vendor/bin/behat

Success! This time the userId is not returned in our JSON.

If you want to know more, check out that annotation reference section. But we’re also going to do more in the next videos.

Leave a comment!

This tutorial uses a deprecated micro-framework called Silex. The fundamentals of REST are still 💯valid, but the code we use can't be used in a real application.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "silex/silex": "~1.0", // v1.3.2
        "symfony/twig-bridge": "~2.1", // v2.7.3
        "symfony/security": "~2.4", // v2.7.3
        "doctrine/dbal": "^2.5.4", // v2.5.4
        "monolog/monolog": "~1.7.0", // 1.7.0
        "symfony/validator": "~2.4", // v2.7.3
        "symfony/expression-language": "~2.4", // v2.7.3
        "jms/serializer": "~0.16", // 0.16.0
        "willdurand/hateoas": "~2.3" // v2.3.0
    },
    "require-dev": {
        "behat/mink": "~1.5", // v1.5.0
        "behat/mink-goutte-driver": "~1.0.9", // v1.0.9
        "behat/mink-selenium2-driver": "~1.1.1", // v1.1.1
        "behat/behat": "~2.5", // v2.5.5
        "behat/mink-extension": "~1.2.0", // v1.2.0
        "phpunit/phpunit": "~5.7.0", // 5.7.27
        "guzzle/guzzle": "~3.7" // v3.9.3
    }
}