Open soullivaneuh opened 8 years ago
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;
}
If I try:
I get a
JMS\Serializer\Exception\UnsupportedFormatException
with messageThe format "form" is not supported for deserialization.
.I have this since I'm using the body converter. Here, my config file:
I'm lost with the documentation. How to enable or implement a serializer for basic form data?