I am using Spring MVC3.2 and Jackson for JSON mapping. I want to serialize and deserialize property name with just number. Here is my class:
public Usage implement Serializable {
private String imei;
#JsonIgnore
#JsonProperty("4")
private long j2j;
#JsonIgnore
#JsonProperty("8")
private long call;
//Getters and setters
}
JSON:
{"imei":"352985052917115", "4":20, "8":10}
Controller:
#ResponseBody
#RequestMapping(value="/alert")
public JsonResult<Void> handleOverUsageAlertByDevice(#RequestBody Usage usage){
//Do something
}
But when I send the JSON to the controller, 404 Bad request error happens, saying:
The request sent by the client was syntactically incorrect.
Can I use number as Json property name?
Your answer would be appreciated.
Yes, "numeric Strings" are perfectly legal JSON names, and Jackson supports them.
So problem should not be with that but something else in request handling.
Please try by setting the content type when sending the request.
The content type should be set as "application/json".
Related
In my REST application developed using SpringBoot and Angular, I need to send a REST request to SpringBoot back end in order to save a object into the database.
In the front end, user fills up a form and submits. Following is the interface from which a object is created in order to be sent to the backend as a REST call.
export interface TenderToPost{
id: number;
name: string;
description: string;
images: File[];
referenceNumber: string;
}
The backend should deserialize the above object to a object of Following class in Java.
public class TenderDTO implements Serializable{
private long id;
private String name;
private String description;
private List<MultipartFile> images;
private String referenceNumber;
// default constructor
// geters and setters
}
As shown above, I need to accept the File sent from frontend as a MultipartFile.
However, when the request is sent from the front end, Jackson gives me the error
Can not construct instance of
org.springframework.web.multipart.MultipartFile: abstract types either
need to be mapped to concrete types, have custom deserializer, or
contain additional type information
I am aware that that this error comes since I have used MultipartFile interface as the type of my images list.
What I thought of as the solution for this, is letting Jackson know to what type the list should be deserialized into using an annotation. So, I used following
#JsonDeserialize(contentAs = CommonsMultipartFile.class)
private List<MultipartFile> images;
CommonsMultipartFile is an implementation of MultipartFile. That is why I used it.
Now I get the following error.
Can not construct instance of
org.springframework.web.multipart.commons.CommonsMultipartFile: no
suitable constructor found, can not deserialize from Object value
(missing default constructor or creator, or perhaps need to add/enable
type information?)
Do I need to change the setter for the images list? Or is my whole approach incorrect?
Kindly show me the way how I should correct this.
Try to use #JsonPropertyDescription to construct object.
#JsonPropertyDescription example
I have XML being fed into a REST controller and I use the #RequestBody annotation to transform that into a Java Object. I need to save the whole XML to a database column in addition to some specific elements from the Java Object. I am marshalling the Java object explicitly to accomplish this and that seems to be duplicate work. Is there a way to get the raw XML in addition to the parsed object while using the #RequestBody annotation?
Yes, there is. Let's say this is your controller method:
public Response yourControllerMethod(#RequestBody YourDTO dto) {
Simply change your #RequestBody parameter type to String and you'll get the raw body of the request:
public Response yourControllerMethod(#RequestBody String rawPayload) {
Or you can even get both:
public Response yourControllerMethod(#RequestBody YourDTO dto, #RequestBody String rawPayload) {
I am using Jersey (JAX-RS) and I'm trying to implement a validation. I have a problem with a response returned by my application when a validation error occurs. Now the response looks like this:
[{
"message": "Custom message",
"messageTemplate": "{custom.message.template}",
"path": "SomeJerseyResource.resourceMethod.arg0.names[0]",
"invalidValue":"[value1, value2]"
}]
where "SomeJerseyResourceClass.resourceMethod" is a JAX-RS resource:
public class SomeJerseyResource {
#POST
#Path("/path")
public Response resourceMethod(#Valid RequestModel request) {
/** method body **/
}
}
and validation constraint is assigned to a getter in RequestModel:
public class RequestModel {
private List<String> names = new ArrayList<>();
#MyConstraint
public List<String> getNames() {
return tags;
}
}
I have a custom ConstraintValidator, where I validate each element of that List.
Problem
I don't want to include resource and method name in "path" field of the response. Instead of
SomeJerseyResource.resourceMethod.arg0.names[0] I want arg0.names[0] only. Client doesn't know about server classes and methods, and he wouldn't be able to properly assign errors to fields when he receives response like that.
I want to customize "invalidValue" field of a response. More specifically, to have only invalid element value, not the whole list in that field.
I didn't find any easy way to do that. Do you have any ideas?
You can just write an ExceptionMapper<ConstraintViolationException> to return the Response of your liking. Jersey uses an ExceptionMapper<ViolationException>. ConstraintViolationException extends from ViolationException, so you're mapper is more specific, and would take precedence in the choosing of the mapper. Jersey's mapper, returns the response as a ValidationError, that's why the body is how it is. But you can make it whatever you want.
If you just want the invalidValue list, then just iterate through the ConstraintViolations from ContraintViolationException.getConstraintViolations(), and get the invalidValue from the ConstraintViolation.
How do I send my custom object in a response. I just want the values printed from my object.
Lets say I have an object of type Person. I am trying to send in REST response body like this.
ResponseBuilder response = Response.ok().entity(personObj);
return response.build();
But I get 500 error.
Tried this one too:
ResponseBuilder response = Response.status(Status.OK).entity(personObj);
return response.build();
Same error.
Tried setting content type as text/xml. No use.
What am I missing here? I tried googling. But not many examples out there, especially with the custom objects;
It returns fine, if I just pass a string to entity() method.
In order to return data from a Resteasy resource method you need to do several things depending on what you are trying to return.
You need to annotate your resource method with the #Produces
annotation to tell Resteasy what the return type of the method should
be.
For example, the method below returns XML and JSON depending on what the client asks for in their Accept header.
#GET
#Produces({MediaType.APPLICATION_JSON,
MediaType.APPLICATION_XML})
public Response foo()
{
PersonObj obj = new PersonObj();
//Do something...
return Response.ok().entity(obj).build();
}
Resteasy supports marshalling the following datatypes by default:
If the datatypes you wish to support are in this table then that
means they are supported by JAXB and all you need to do is annotate
your PersonObj class with JAXB annotations to tell it how to
marshall and unmarshall the object.
#XmlRootElement
#XmlType(propOrder = {"firstName", "lastName"})
public class PersonObj
{
private String firstName;
private String lastName;
//Getters and Setters Removed For Brevity
}
What if your content-type is not supported out of the box?
If you have a custom content-type that you would like to marshall then you need to create a MessageBodyWriter implementation that will tell Resteasy how to marshall the type.
Provider
#Produces({"application/x-mycustomtype"})
public class MyCustomTypeMessageBodyWriter implements MessageBodyWriter {
}
Just implement the interface and register it like any other Provider.
If you would like to read a custom content-type then you need to implement a custom MessageBodyReader to handle the incoming type and add it to the #Consumes annotation on your receiving method.
I have this DTO to be converted to XML/JSON and send response to client from my web service. We are using Jersey.
#XmlRootElement(name = "response")
public class Response {
#XmlValue
private String value="true";
}
It is getting properly converted to XML,
<response>true</response>
but json is missing out the parent tag,
it is outputting true instead of response:true
Is anybody having the same problem?
Values don't get modified with the parent names. One thing is metadata (tags), and other thing is data, that doesn't get modified.
It is actually because we are omitting parent tag while outputing JSON.
Just in this case omitting parent tag is causing problem as there is only one value in the object.