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

Missing documentation to register a new encoder #994

Closed
matt6697 opened this issue Nov 24, 2019 · 3 comments · May be fixed by #1797
Closed

Missing documentation to register a new encoder #994

matt6697 opened this issue Nov 24, 2019 · 3 comments · May be fixed by #1797

Comments

@matt6697
Copy link

I'm trying to register a new encoder following the https://api-platform.com/docs/core/content-negotiation/ Supporting custom format example.

However, I get a "Serialization for the format myformat is not supported"when accessing API Platform after having followed the documented example.

{
  "type": "https://tools.ietf.org/html/rfc2616#section-10",
  "title": "An error occurred",
  "detail": "Serialization for the format myformat is not supported",
  "trace": [
    {
      "namespace": "",
      "short_class": "",
      "class": "",
      "type": "",
      "function": "",
      "file": "/mnt/c/Users/matthieu/Documents/GitHub/SPMetadataParser/vendor/symfony/serializer/Serializer.php",
      "line": 121,
      "args": []
    },
    {
      "namespace": "Symfony\\Component\\Serializer",
      "short_class": "Serializer",
      "class": "Symfony\\Component\\Serializer\\Serializer",
      "type": "->",
      "function": "serialize",
      "file": "/mnt/c/Users/matthieu/Documents/GitHub/SPMetadataParser/vendor/api-platform/core/src/EventListener/SerializeListener.php",
      "line": 119,
      "args": [
        [
          "object",
          "ApiPlatform\\Core\\Api\\Entrypoint"
        ],
        [
          "string",
          "myformat"
        ],
        [
          "array",
          []
        ]
      ]
    },
[...]

Step 1 : Created a custom encoder class following the https://symfony.com/doc/current/serializer/custom_encoders.html documentation
For the test and to match the reference documentation, the encoder returns a yaml content.

It is not clear at all in the documentation how to link the myformat new format with the MyFormatEncoder class. I used the const FORMAT = 'myformat'; to miror how the XML encoder class is created, but I might be wrong.

<?php
namespace App\Serializer\Encoder;

use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Yaml\Yaml;

class MyFormatEncoder implements EncoderInterface, DecoderInterface
{
    const FORMAT = 'myformat';

    public function encode($data, $format, array $context = [])
    {
        return Yaml::dump($data);
    }

    public function supportsEncoding($format)
    {
        return 'yaml' === $format;
    }

    public function decode($data, $format, array $context = [])
    {
        return Yaml::parse($data);
    }

    public function supportsDecoding($format)
    {
        return 'yaml' === $format;
    }
}

Step 2 : Registered the custom encoder class following the https://symfony.com/doc/current/serializer/custom_encoders.html documentation using the serializer.encoder tag

services:
    [....]
    # add more service definitions when explicit configuration is needed
    # please note that last definitions always *replace* previous ones
    'App\Serializer\Encoder\MyFormatEncoder':
        tags: [ 'serializer.encoder' ]

Step 3 : Registered custom format in api_platform.yaml

api_platform:
    formats:
      myformat: ['application/vnd.myformat']
    mapping:
        paths: ['%kernel.project_dir%/src/Entity']
    patch_formats:
        json: ['application/merge-patch+json']
    swagger:
        versions: [3]

An update of https://api-platform.com/docs/core/content-negotiation/ might be required to beter describe how to register a custom API Platform encoder as the https://symfony.com/doc/current/serializer.html#adding-normalizers-and-encoders and https://symfony.com/doc/current/serializer/custom_encoders.html are not clear at all about the new encoder and format registration process.

@antograssiot
Copy link
Contributor

in your case if you want this to work with your custom 'myformat' format, then just update your encoder because right now public function supportsDecoding($format) and public function supportsEncoding($format) will always returning false. the following will do the trick

    public function supportsEncoding(string $format): bool
    {
        return self::FORMAT === $format;
    }

    public function supportsDecoding(string $format): bool
    {
        return self::FORMAT === $format;
    }

Then once your encoder will be able to respond correctly you should be good.
Feel free to close or to give more detail of what can be improved on the documentation, or provide directly a pull request on the documentation repository

@matt6697
Copy link
Author

Many thanks for the trick.

The functions have to be slightly modified to be compatible with Symfony\Component\Serializer\Encoder\EncoderInterface (string type has to be removed for $format parameter)

public function supportsEncoding($format): bool {
    return self::FORMAT === $format;
  }

  public function supportsDecoding($format): bool {
    return self::FORMAT === $format;
  }

I'll will test the custom format tomorrow and then work on a pull request to describe the custom encoder registration process in the content negociation API Platform documentation.

@antograssiot
Copy link
Contributor

(string type has to be removed for $format parameter)

that depends on your Symfony version actually 🤣

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

Successfully merging a pull request may close this issue.

2 participants