how to convert json in POST to javaBean - java

here is my provider:
class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"
here is my javaBean
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonRootName;
#JsonRootName("issue")
public class TestBean {
#JsonProperty("project_id")
private Integer projectId;
#JsonProperty("subject")
private String subject;
public Integer getProjectId() {
return projectId;
}
public void setProjectId(Integer projectId) {
this.projectId = projectId;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
}
here is my service
#WebService
public class IssueRestfulApi {
#POST
#Path("/create")
#Consumes(value = {MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public void createIssue(TestBean bean) {
System.out.println(bean.getSubject());
System.out.println("get create request");
}
}
then i send post request like this :
{"issue": {
"project_id": 1,
"subject": "Example"
}
}
finally I get this exception :
Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "issue" (Class com.rakuten.tranp.api.bean.TestBean), not marked as ignorable
at [Source: org.apache.cxf.transport.http.AbstractHTTPDestination$1#783478b0; line: 1, column: 12] (through reference chain: com.rakuten.tranp.api.bean.TestBean["issue"])
at org.codehaus.jackson.map.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:53)
at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:267)
at org.codehaus.jackson.map.deser.std.StdDeserializer.reportUnknownProperty(StdDeserializer.java:673)
at org.codehaus.jackson.map.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:659)
at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:1365)
at org.codehaus.jackson.map.deser.BeanDeserializer._handleUnknown(BeanDeserializer.java:725)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:703)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:580)
at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2704)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1315)
at org.codehaus.jackson.jaxrs.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:419)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSUtils.java:1311)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1262)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:801)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:764)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:212)
... 28 more
how to solve this question, please help me,
Thank your every much ,
regurd.

Add this property in your application.property file and then try again:
spring.jackson.deserialization.UNWRAP_ROOT_VALUE=true

The error stack trace is straightforward and fair enough to identify the problem:
Unrecognized field "issue" (Class com.rakuten.tranp.api.bean.TestBean)
It means that you are trying to post a JSON with a property ìssue, this is what we can see in your JSON, which doesn't exist in your Java Bean so it causes this Exception because the property isn't recognized and can't be mapped.
Solution:
So you need to change your JSON to include only the inner properties of your issueobject:
{
"projectId": 1,
"subject": "Example"
}
EDIT:
If you can't change your JSON then you need to have two POJO classes:
First one Issue with the two properties projectId and subject
as you wrote in your TestBean class.
Second is TestBean that should only accept an object of type
Issue.

Related

Ignore RootNode and custom mapping in Jackson/spring/Java

How i can ignore rootname if I dont need it? I need only bill.
if I remove "version" from json work fine..
my error on console log
2019-07-27 19:20:14.874 WARN 12516 --- [p-nio-80-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected token (FIELD_NAME), expected END_OBJECT: Current token not END_OBJECT (to match wrapper object with root name 'bill'), but FIELD_NAME; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (FIELD_NAME), expected END_OBJECT: Current token not END_OBJECT (to match wrapper object with root name 'bill'), but FIELD_NAME
at [Source: (PushbackInputStream); line: 8, column: 2]]
my json look like this
{
"bill":
{
"siteId":"gkfhuj-00",
"billId":"d6334954-d1c2-4b51-bb10-11953d9511ea"
},
"version":"1"
}
my class for json
i try use JsonIgnoreProperties but its dont help also i write "version"
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonRootName(value = "bill")
public class Bill {
private String siteId;
private String billId;
//getters and setters
my post method lisen object Bill
#PostMapping("/bill")
#ResponseBody
public ResponseEntity<String> getBill(#RequestBody Bill bill)
As you are relying on the Spring boot through annotations and Jackson, custom deserializer will work flawless in here. You have to create the deserializer class as show below
public class BillDeserializer extends StdDeserializer<Bill> {
public BillDeserializer() {
this(null);
}
public BillDeserializer(Class<?> vc) {
super(vc);
}
#Override
public Bill deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode billNode = jp.getCodec().readTree(jp);
Bill bill = new Bill();
bill.setSiteId(billNode.get("bill").get("siteId").textValue());
bill.setBillId(billNode.get("bill").get("billId").textValue());
return bill;
}
}
Now you have to instruct your Jackson to use this deserializer instead of the default one for the Bill class. This is done by registering the desearilizer. It can be done through a simple annotation on the Bill class like #JsonDeserialize(using = BillDeserializer.class)
Your Bill class will typically look as specified below
#JsonDeserialize(using = BillDeserializer.class)
public class Bill {
private String siteId;
private String billId;
//getters and setters
}

Jackson 2.5 - JsonMappingException: Missing external type id property

I have this class with an External Property "contentType":
public class ContentEvent implements AbstractMessagingEvent{
#Valid
#JsonTypeInfo(include = JsonTypeInfo.As.EXTERNAL_PROPERTY, use = NAME, property = "contentType")
public final ContentValue message;
public ContentEvent(ContentValue message) {
this.message = message;
}
public ContentEvent() {
this(null);
}
public static ContentEvent example () {
return new ContentEvent(HostedFile.example());
}
}
"contentType" can be one of the following:
#JsonSubTypes({
#JsonSubTypes.Type(SecureFormSubmission.class),
#JsonSubTypes.Type(SecureFormInvitation.class),
#JsonSubTypes.Type(TextPlain.class),
#JsonSubTypes.Type(HostedFile.class),
#JsonSubTypes.Type(ExternalFile.class)
})
public interface ContentValue{
}
When I try to deserialize a JSON which is missing the "contentType" field, I get the following error:
com.fasterxml.jackson.databind.JsonMappingException: Missing external type id property 'contentType'
I tried adding a 'defaultImpl=NoClass.class' and also a defaultImpl=MyOwnCustomClass' and it clears the error, but the result is an object without any 'contentType'.
What I want is in case the 'contentType' field is missing, to use a default.
Thanks in advance.
You can annotate the class with #JsonIgnoreProperties(ignoreUnknown=true).

springboot Can not deserialize-HttpMessageNotReadableException

I am trying to read json in my spring boot project.
My JSON data is as follows:
[{
"userId":"101"
},
{
"partNum":"aaa"
},
{
"partNum":"bbb"
},
{
"partNum":"ccc"
}]
I have created a DTO class:
public class TcPartDto {
private String userId;
private List<String> partNum;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public List<String> getPartNum() {
return partNum;
}
}
And I am calling it in my Controller as follows:
#RequestMapping(value = "/volumeinfo", method = RequestMethod.POST, consumes = {"application/json"}, produces = {"application/json"})
#ResponseBody
public List<TcPartVolumeDto> volumeinfo(#RequestBody TcPartDto partList) throws Exception {
return tcService.fetchVolumeInfo(partList);
}
But I get the following error:
Through Postman I get this error:
"Could not read document: Can not deserialize instance of
tc.service.model.TcPartDto out of START_ARRAY token\n at [Source:
java.io.PushbackInputStream#5359141a; line: 1, column: 1]; nested
exception is com.fasterxml.jackson.databind.JsonMappingException: Can
not deserialize instance of tc.service.model.TcPartDto out of
START_ARRAY token\n at [Source: java.io.PushbackInputStream#5359141a;
line: 1, column: 1]"
What wrong am I doing?
The DTO you've created does not match the json data it's trying to read.
Based on your DTO sample json should be:
{
"userId" : "someId",
"partNum" : [ "partNum1", "partNum2"]
}
otherwise if json object you're consuming is fixed then DTO should be:
public class MyDTO {
private String userId;
private String partNum;
// ...
}
and with your controller with a parameter of type
List<MyDTO>
You are sending a JSON Array to your public List<TcPartVolumeDto> volumeinfo(#RequestBody TcPartDto partList) method. But it should be deserialize to a single object: TcPartDto partList.
Change your JSON structure to send only a single TcPartDto or make sure your that your volumeinfo method can receive an Array or List.
And you have to change your JSON structure in case you want to send a single object:
{
"userId": 101,
"partNum": [
"aaa",
"bbb",
"ccc"
]
}
As others already pointed out various answers.
if in case this is the json that you want to map without changing the class :
JSON:
[{
"userId":"101"
},
{
"partNum":"aaa"
},
{
"partNum":"bbb"
},
{
"partNum":"ccc"
}]
Class:
#JsonIgnoreProperties(ignoreUnknown=true)
public class TcPartDto {
private String userId;
private List<String> partNum;
//getters and setters
}
Controller:
#RequestMapping(value = "/volumeinfo", method = RequestMethod.POST, consumes = {"application/json"}, produces = {"application/json"})
#ResponseBody
public List<TcPartVolumeDto> volumeinfo(#RequestBody TcPartDto[] partArray) throws Exception {
return tcService.fetchVolumeInfo(partArray);
}
Output:
[{"userId":"101","partNum":null},{"userId":null,"partNum":["aaa"]},{"userId":null,"partNum":["bbb"]},{"userId":null,"partNum":["ccc"]}]

Spring #RequestBody Bad Request

I am using POSTMAN to send request's.
Configured all right there:
Content-Type application/json
Request Type POST
and in Body I have the following:
{
"token":"EAACEdEose0cBAFLc4blCYmmetEMBEZCiQQZAuvz6DlxFt0yPZCksZBWv09B71aZCeDH9zOPyzM44GRl8WA56uFZBmOiUMmSlk3USfOwRdwmXDnhlPArttzjjLzUXaTReHzHZC7ZCcFzZADwGBLRUHvTb17nagRDLpZBysdxZBxuJuojlgZDZD"
}
I POST this to a controller and get a 400 BAD Request Error:
{
"timestamp": 1475061564742,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "Could not read document: Can not construct instance of at.wastun.controller.WTUserController$RegisterBody: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)\n at [Source: java.io.PushbackInputStream#a646ac6; line: 2, column: 2]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of at.wastun.controller.WTUserController$RegisterBody: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)\n at [Source: java.io.PushbackInputStream#a646ac6; line: 2, column: 2]",
"path": "/users/register"
}
The class and the Controller looks like:
#Controller
#RequestMapping("/users")
#ResponseBody
public class WTUserController {
private class RegisterBody{
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public RegisterBody(String fbToken){
this.token = fbToken;
}
}
#RequestMapping(value="/register", method = RequestMethod.POST)
public String method0(#RequestBody RegisterBody body){
return body.getToken();
}
}
Your RegisterBody class is private. So nothing outside of the code in your class can create new instances of it. Try:
public static class RegisterBody {
Or, better still, move RegisterBody into its own java file.
The error itself tells you about origin of the problem: no suitable constructor found. So you need to add default constructor into RegisterBody class. Also I'm not sure that making this class private good idea.
It was a combination of both answers #Andremoniy and #Mr Spoon
Worked after I made the class
public static class RegisterBody {
and removed the constructor and made it to an default constructor.
public static class RegisterBody{
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
Works now thanks
When Spring tries to resolve Body it creates the object with a default constructor ClassName() and then tries to fill the fields with setters. So if you want to resolve RequestBody into RegisterBody it should look like below:
private class RegisterBody{
private String token;
public RegisterBody() {};
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public RegisterBody(String fbToken){
this.token = fbToken;
}
}
Apart from that remember, that Spring implements MVC for some reason. Put the classes to Utils or Misc package if you can't classify it better but DON'T declare classes in Controllers!
Try to add an empty constructor for the class.
If you're using Lombok you can use the following annotations:
#Getter
#Setter
#AllArgsConstructor
// Must include this annotation since Spring instantiates the #ResponseBody type with no args.
#NoArgsConstructor
public class CustomRequestBody {
private String message;
}
#Slf4j
#RestController
public class ReactiveRestController {
#PostMapping("/api/test")
public Mono<CustomResponse> post(#RequestBody CustomRequestBody requestBody) {
log.info(requestBody.getMessage());
return Mono.just(new CustomResponse(200, "success"));
}
}

How can i passing two parameters to restful web service using http post? UnrecognizedPropertyException: Unrecognized field , not marked as ignorable

My course pojo is ;
public class Course {
private int cid;
private String name;
private String code;
private int credit;
//Getters Setters
}
service :
#RequestMapping(value="/addcourse" , method=RequestMethod.POST)
public #ResponseBody Response<Course> addCoursetoUser(#RequestBody Course course, #RequestBody User user) throws SQLException{
if(new CourseDAO().addCoursetoUser(course, user))
return new Response<>(...);
else
return new Response<>(...);
}
i am trying to send this json values to my web service, but i am getting this error :
org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "cid" (Class com.spring.model.Course), not marked as ignorable
{
"id" :3,
"name" : "Algorithms",
"code" : "COM367",
"credit" : 3,
"cid" : 28,
"username" : "selin",
"password" : "ssgg"
}
I have tried a lot of jsons but I always get this error.
Thanks in advance..
You can't. You will need to wrap your two objects into a single object (maybe CourseUser or CourseUserRequest).
Also that error implies your Course class is missing the cid field in the Java model.
First of all you need to write getter and setter method for all class members which you have declared in your pojo :
eg :
public class Course {
private int cid;
public int getCid()
{
return this.cid ;
}
public void setCid(int cid)
{
this.cid=cid;
}
}
Second
You can not have two request body param in your post method here either you need to define a parent pojo which has Course and User Pojo like this
public class MyClass{
private Course course ;
private User user ;
// getter setter for User and Course
}
Of Course your json will be change if you use this like :
{
"course.id" :3,
"course.name" : "Algorithms",
"course.code" : "COM367",
"course.credit" : 3,
"course.cid" : 28,
"user.username" : "selin",
"user.password" : "ssgg"
}

Categories

Resources