I'm developing a GWT web application with a RESTful web service. The web service's results are deserializing to POJO with Jackson 1.8. It's work fine with simple fields. However, it fails when it try to deserialize a list of POJO. This is the POJO with list to deserialize:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class DatosIndicadoresSVclaveDTO implements Serializable {
...
#XmlAttribute
#JsonDeserialize(contentAs = IdeologicoVOXDTO.class)
public List<IdeologicoVOXDTO> ideologicoVox;
...
//getter/setters
}
And this is the POJO that contains the list
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class IdeologicoVOXDTO implements Serializable {
#XmlAttribute
private Integer numeroPalabra;
#XmlAttribute
private String palabra;
#XmlAttribute
private Integer categoria;
...
//getter/setters
}
The JSON have this structure:
{datosIndicadoresSVclave: {
...
"ideologicoVox":[
{
"categoria":"1",
"numeroPalabra":"1",
"palabra":"abandonado",
...
},
{
"categoria":"2",
"numeroPalabra":"3",
"palabra":"hambre",
...
}
],
...
}
}
When it's running, the web service's results works fine, but the deserialize print this error:
SEVERE: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
at [Source: java.io.StringReader#10b61ad; line: 1, column: 580] (through reference chain: org.ull.etsii.client.dto.DatosIndicadoresSVclaveDTO["ideologicoVox"])
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:219)
at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:212)
Any idea?? Thanks!!
I had faced some similar kind of problem and tried the following way, and it worked for me.
Create a new class which contains property
~ public List ideologicoVox ~
And use this class reference as property to the main class i.e ~ DatosIndicadoresSVclaveDTO
I've solved!!
The problem is the size list is variable, and it fails if it has one element. The Jackson's version is 1.7, that it can't accept arrays single value. My solution is GSON with a custom register type, and I've used the Joshi's adviced. It works great!! Thanks!!
Related
I would need to convert JSON to POJO, which implements following marker interface:
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.io.Serializable;
#JsonTypeInfo(
use = JsonTypeInfo.Id.CLASS,
include = JsonTypeInfo.As.PROPERTY,
property = "#class"
)
public interface MyInterface extends Serializable {
}
this is pojo:
public class MyPojo implements MyInterface
{
private static final long serialVersionUID = 1L;
private String phonetype;
private String cat;
//getters + setters
}
and this is snippet code where I have to use it, but I don't know what I have to do:
String json = "{\"phonetype\":\"N95\",\"cat\":\"WP\"}";
ObjectMapper mapper = new ObjectMapper();
MyPojo myPojo = mapper.readValue(json, MyPojo.class);//here I get exception: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class path.to.MyPojo]: missing type id property '#class'
// at [Source: (String)"{"phonetype":"N95","cat":"WP"}"; line: 1, column: 30]
When I don't implement interface into MyPojo, everything works correctly without exception, but I would need implement it.
I use library jackson-databind-2.9.8
I would like to asking you, if you have any suggestion how can I solve it or if does it exist another approach how parse Pojo implementing interface showed above. I mean something missing in my interface but I don't know what.
Thank you so much
You may try to use a custom deserializer as shown in the following link How arbitrary JSON string can be deserialized to java POJO?
I am using Spring Boot to create a web application. One of the endpoints expect a json object having one property, i.e. studentId. I am using DTO like my other functions to capture the payload.
#PostMapping("/courses/{id}/students")
public SuccessResponse<Void> addEnrolls(#PathVariable Long id, #RequestBody StudentIdPayload payload) throws HandledException {
courseService.addEnrolls(id, payload.getStudentId());
return success(HttpStatus.OK);
}
#Data
#AllArgsConstructor
public class StudentIdPayload {
private Long studentId;
}
But when I tried to post the endpoint with json body {"studentId":1}, I got the following error :
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.bimoadityar.univms.dto.input.StudentIdPayload` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
While it works if I post using just the value 1.
How can I get it to work with the object payload?
Interestingly, when I add another property to the StudentIdPayload, such as String placeholder, it works as intended, although this solution feels hacky.
Considering https://github.com/FasterXML/jackson-databind/issues/1498, it seems that this is the intended behavior.
For my particular case, I am satisfied with adding the #JsonCreator to my constructor.
#Data
#AllArgsConstructor(onConstructor = #__(#JsonCreator))
public class StudentIdPayload {
private Long studentId;
}
By default, deserialization requires no-args constructor, so add #NoArgsConstructor:
#Data
#AllArgsConstructor
#NoArgsConstructor
public class StudentIdPayload {
private Long studentId;
}
see also:
Annotations: using custom constructor
I am using com.fasterxml.jackson.databind in a spring boot application. When I send a request to my endpoint I receive the following exception:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of
org.pacakge.domain.controller.Mycontroller (although at least one Creator exists): cannot
deserialize from Object value (no delegate- or property-based Creator)\n at
[Source: (PushbackInputStream); line: 2, column: 3] Is the body of the request formatted correctly?
My controller processes a request body that has the following structure:
{
"portalId": 123,
"objectType": "TYPE",
"objectTypeId": "0-3",
"objectId": 123,
"properties": { ... }
}
The only property that I need is objectId. I've constructed a class to process this object like so:
#lombok.Value
private static class MyObject {
#JsonAlias("objectId")
private final String dealId;
}
I've designed a controller that looks like this
#Slf4j
#RestController
#RequestMapping(path = "/entrypoint")
public class MyController {
#Autowired
public MyController(){}
/**
* REST endpoint handles MyObject
*/
#PostMapping(value = "/endpoint")
public void handleRequest(
#Valid #RequestBody MyObject command
) {
log.debug(command.getDealId());
}
#lombok.Value
private static class MyObject {
#JsonAlias("objectId")
private final String dealId;
}
}
What is interesting about this problem is that my request is processed just fine if I change MyObject to the following structure:
#lombok.Value
private static class MyObject {
#JsonAlias("objectId")
private final String dealId;
private final JSONObject properties; // TODO we shouldn't need this. Fix.
}
I cannot seem to figure out what the issue is. I would love some help on this problem. Maybe there is annotation that I am missing? I am hoping someone else has experienced this issue. I haven't found any information on it by just searching the web.
I added the following line to lombok.config in the root directory of the project:
lombok.anyConstructor.addConstructorProperties=true
And after that managed to deserialize your JSON using this DTO using #JsonIgnoreProperties annotation:
#Value
#JsonIgnoreProperties(ignoreUnknown = true)
public class MyObject {
#JsonProperty("objectId")
String dealId;
}
I want one of the String member variables in my Spring Boot Java #Entity model class to show up as an actual JSON object when sent to the client side, but I am not sure how this is possible
I have this #Entity class in Spring Boot :
#Entity
#Data
public class A {
#JsonProperty
private String value
}
That "value" in the class A is supposed to be a JSON object, but I had to keep it in string type or it won't save into the DB by JPA.
When the controller returns this model object to the client side, the "value" in the JSON string will show up as a full string instead of a JSON struct.
i.e.
This shows up
{
"value": "{\"another_value\":\"1234\"}"
}
instead of
{
"value": {"another_value":"1234"}
}
Is there some easy way to annotate the "value" in my class A to fix this?
Thanks
You have to provide a custom Getter for converting it while de-serializing. I am using google gson for deserializing.
#Entity
#Data
public class A {
#JsonProperty
private String value;
#JsonGetter("value")
public HashMap getValueAsJson(){
return new Gson().fromJson(value, HashMap.class);
}
}
I am sending the following JSON object to my Java Spring application
{
"ewsUrl":"https://dummy.url.com",
"ewsIdentityToken":"12345",
"itemIds":["itemids"],
"entityId":null,
"documentType":"Dummy",
"documentStatus":"Record",
"filename":"message.eml",
"metadata":{"title":"message"}
}
I have defined an object public class RequestObject and in my controller I have
public RequestObject
testMyStuff(#CurrentUser User currentUser,
#RequestBody RequestObject myDummyObject) throws Exception {
return myDummyObject
}
My application returns the error Could not read document: Root name 'ewsUrl' does not match expected ('RequestObject') for type...etc
However if I send the JSON formatted like this it successfully maps the object:
{ "RequestObject":
{
"ewsUrl":"https://dummy.url.com",
"ewsIdentityToken":"12345",
"itemIds":["itemids"],
"entityId":null,
"documentType":"Dummy",
"documentStatus":"Record",
"filename":"message.eml",
"metadata":{"title":"message"}
}
}
I do not want to name the object in my JSON, I want to send as described in the first example. How do I achieve this?
UPDATE:
RequestObject.java
public class RequestObject {
public String ewsUrl;
public String ewsIdentityToken;
public String[] itemIds;
public String entityId;
public String documentType;
public String documentStatus;
public String filename;
public Metadata metadata;
public RequestObject() {
}
public static class Metadata {
public String title;
}
}
UPDATE2:
The way it is described in this example suggests that the object does not need to be named in the JSON data in the POST request. I think I am emulating this example, but I'm getting different results.
Is there a configuration for Jackson/Spring that I am missing?
Update 3:
The complete error message is:
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException:
Could not read document:
Root name 'ewsUrl' does not match expected ('RequestObject') for type
[simple type, class uk.co.test.RequestObject] at [Source:
java.io.PushbackInputStream#7e223182; line: 2, column: 9];
nested exception is com.fasterxml.jackson.databind.JsonMappingException:
Root name 'ewsUrl' does not match expected ('RequestObject') for type
[simple type, class uk.co.test.RequestObject]
There's some configuration settings that look like they can be defined for the ObjectMapper that controls the behaviour of the root element:
https://fasterxml.github.io/jackson-databind/javadoc/2.0.0/com/fasterxml/jackson/databind/DeserializationFeature.html#UNWRAP_ROOT_VALUE - see SerializationFeature.html#WRAP_ROOT_VALUE as well.
UNWRAP_ROOT_MODULE is disabled by default according to the docs so not sure why you're seeing the behaviour you are.
Config example for spring is available at
http://docs.spring.io/spring-framework/docs/3.2.3.RELEASE/javadoc-api/org/springframework/http/converter/json/JacksonObjectMapperFactoryBean.html
Just use JSONArray instead of JSONObject
Update
You can get your Json Object via JSONArray.getJSONObject()