If I try:
curl -s -X POST http://localhost:8000/api/backup/models -d code=test
I get a JMS\Serializer\Exception\UnsupportedFormatException with message The format "form" is not supported for deserialization..
I have this since I'm using the body converter. Here, my config file:
fos_rest:
routing_loader:
default_format: json
body_converter:
enabled: true
validate: true
serializer:
serialize_null: true
view:
formats:
xml: false
json: true
rss: false
yml: true
view_response_listener: force
param_fetcher_listener: force
format_listener:
rules:
- { path: '^/api/', priorities: ['json', 'yml'], fallback_format: json, prefer_extension: true }
- { path: '^/', stop: true } # FOSRest should not handle other routes than API
media_type:
enabled: true
I'm lost with the documentation. How to enable or implement a serializer for basic form data?
The error is:
"message": "The format \"form\" is not supported for deserialization.",
"class": "Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException",
Have you find some solution ?
Actually not.
At least a form class deserializer
use JMS\Serializer\GenericDeserializationVisitor;
/**
* Class FormDeserializationVisitor
* @package HOB\CommonBundle\Serializer
*/
Class FormDeserializationVisitor extends GenericDeserializationVisitor
{
/**
* @param $str
* @return array
*/
protected function decode($str)
{
parse_str($str, $output);
return $output;
}
}
And service configuration:
jms_serializer.array_deserialization_visitor:
class: HOB\CommonBundle\Serializer\FormDeserializationVisitor
arguments: [ '@jms_serializer.naming_strategy', '@jms_serializer.object_constructor' ]
tags:
- { name: jms_serializer.deserialization_visitor, format: form }
Working on my side
I also have this problem when using the body converter. The error disappears when providing the header Content-Type: application/json in the request.
I'm looking for a way too set JSON as de default content type of the body message, is this possible? As an alternative I would like to send a more readable error message when not providing the Content-Type in the request. What's the best way to implement this?
I don't think that what you want @mdriessen is compliant to HTTP. The request content, if not empty must have a Content-Type imo.
Well I found a body_listener -> default_format config so I would assume it is possible. But the error still persists even when setting a default so I don't know. #920
Apparently the body_listener uses Request::getRequestFormat which is weird as it is related to the response...
So I think it conflicts here with the format_listener.
Can you provide me your config ?
Ofcourse, thanks for looking into this!
The /api/* route is giving me this error when using POST.
fos_rest:
allowed_methods_listener: true
access_denied_listener:
json: true
body_listener:
default_format: json
decoders:
json: fos_rest.decoder.jsontoform
body_converter:
enabled: true
validate: true
format_listener:
rules:
- { path: '^/api/*', priorities: ['json'], fallback_format: 'json', prefer_extension: true }
- { path: '^/*', priorities: ['html', 'json', 'xml', 'css', '*/*'], fallback_format: 'html', prefer_extension: true }
routing_loader:
include_format: false
serializer:
serialize_null: true
view:
serialize_null: true
view_response_listener: true
formats:
json: true
xml: true
rss: false
templating_formats:
html: true
mime_types:
png: ['image/png']
exception:
enabled: true
Are you using the body converter when the error occurs ?
Can you also copy-paste your controller and your request headers/parameters ?
Ok I understood the issue (in fact your issue @mdriessen is not exactly the same as the original). It doesn't seem related to FOSRestBundle but to JMSSerializerBundle which doesn't support forms by default.
The solution of @acassan looks good to me to fix it.
Then @mdriessen you pointed the fact that it is not possible to define a default format for the body converter, this should be added but probably won't before 2.1 (which will be released in a few months).
As a workaround, you can create a kernel.request listener setting a default Content-Type when none is provided.
I did some debugging of the BodyListener and I noticed that my REST Client actually sends Content-Type: */* when not explicitly providing one. In the BodyListener this results to Request::getFormat which returns null and the default value is used. All good here it seems.
But further in the request the AbstractRequestBodyParamConverter::execute is called which in turn calls Serializer::deserialize with format parameter Request::getContentType, in my case this returns null. If I change this to Request::getRequestFormat it works like expected.
Am I missing something or is this a bug? Or is this the 2.1 feature you are talking about, a default format for the body converter?
I've made a kernel.request listener to set the default Content-Type as a workaround, working as expected now. Thanks for your help and I'm looking forward to 2.1, keep up the good work!
I had same problem. I fix it with creation ParamConverter for image data type:
https://github.com/onekit/rest-tutorial/blob/master/src/AppBundle/Request/ContactPictureParamConverter.php
Config of fos_rest:
fos_rest:
routing_loader:
default_format: json
param_fetcher_listener:
enabled: true
force: true
body_listener:
decoders:
json: fos_rest.decoder.jsontoform
body_converter:
enabled: true
validate: true
view:
formats:
json: true
templating_formats:
html: true
force_redirects:
html: true
failed_validation: HTTP_BAD_REQUEST
default_engine: twig
view_response_listener: "force"
exception:
enabled: true
service:
view_handler: fos_rest.view_handler.default
https://github.com/onekit/rest-tutorial/blob/master/app/config/config.yml#L137-L165
Add ParamConveter as service:
api.converter.contact_picture:
class: AppBundle\Request\ContactPictureParamConverter
arguments: ['@fos_rest.validator']
tags:
- { name: request.param_converter, converter: api.converter.contact_picture }
https://github.com/onekit/rest-tutorial/blob/master/app/config/services.yml#L42-L46
In Controller on end point method in annotation say use for your field chosen annotation:
/**
* @ApiDoc(
* parameters={
* {"name"="image", "dataType"="file", "required"=true, "description"="contact picture"}
* },
* views = {"default", "admin"}
* )
*
* @Sensio\Security("has_role('ROLE_ADMIN')")
* @Rest\Post("/{id}/picture", name="api_post_contact_picture", requirements={"id" = "\d+"})
* @Sensio\ParamConverter("picture", converter="api.converter.contact_picture")
* @Rest\View(serializerGroups={"default", "contact_picture"})
*
* @param Contact $contact
* @param ContactPicture $picture
* @param ConstraintViolationListInterface $validationErrors
* @return Contact|Response
*/
public function postPictureAction(Contact $contact, ContactPicture $picture, ConstraintViolationListInterface $validationErrors)
{
if ($validationErrors->count()) {
return $this->handleError('Validation errors', $validationErrors);
}
$contact = $this->contactManager->setPicture($contact, $picture);
return $contact;
}
https://github.com/onekit/rest-tutorial/blob/master/src/AppBundle/Controller/Api/PictureContactController.php#L47-L72
Most helpful comment
I also have this problem when using the body converter. The error disappears when providing the header Content-Type: application/json in the request.
I'm looking for a way too set JSON as de default content type of the body message, is this possible? As an alternative I would like to send a more readable error message when not providing the Content-Type in the request. What's the best way to implement this?