I’m trying to send a JSON to a POST bodyRequest service to use this information as a Java ArrayList or something like that. When I try to do it, I receive a deserialize error
This is my JSON:
{information: [ {fields: “Periods Offered”, tables: “Courses”,
columns: “Academic Level*”}, {fields: “Default Grading Basis*”,
tables: “Courses”, columns: “Default Offering Percentage”}, {fields:
“Allowed Locations”, tables: “Courses”, columns: “Allowed to Offer”}
] }
This is my POST bodyRequest service
@ResponseBody @PostMapping("/dataMapping/update/table") public ResponseEntity<Object> updateDataMappingTable(@RequestBody List<UpdateDataMapping> information) { try { String update = this.dataMappingService.update(information); return new ResponseEntity<Object>(update, HttpStatus.OK); } catch (Exception e) { Response response = new Response(); response.setError(e.getMessage()); return new ResponseEntity<Object>(response, HttpStatus.OK); } }
My UpdateDataMapping class looks like:
public class UpdateDataMapping { public String fields; public String tables; public String columns; public UpdateDataMapping() { } public UpdateDataMapping(String fields, String tables, String columns) { this.fields = fields; this.tables = tables; this.columns = columns; } public String getFields() { return fields; } public void setFields(String fields) { this.fields = fields; } public String getTables() { return tables; } public void setTables(String tables) { this.tables = tables; } public String getColumns() { return columns; } public void setColumns(String columns) { this.columns = columns; } }
This is my error:
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of
java.util.ArrayList<com.kastech.model.UpdateDataMapping>
out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance ofjava.util.ArrayList<com.kastech.model.UpdateDataMapping>
out of START_OBJECT token
at [Source: (PushbackInputStream); line: 1, column: 1]]
If someone can help me I will appreciate it.
Advertisement
Answer
Your JSON example shows that your array is delivered inside an information
object. You are seeing your current stack trace because the Jackson is unable to find an appropriate way to deserialize your request payload.
Either, you can change your request JSON to simply be a list
[ {fields: "Periods Offered", tables: "Courses", columns: "Academic Level*"}, {fields: "Default Grading Basis*", tables: "Courses", columns: "Default Offering Percentage"}, {fields: "Allowed Locations", tables: "Courses", columns: "Allowed to Offer"} ]
or you can have a POJO represent that information
object
class UpdateMappingList { List<UpdateDataMapping> information; ... }
7 People found this is helpful
MismatchedInpuException is base class for all JsonMappingExceptions. It occurred when input is not mapping with target definition or mismatch between as required for fulfilling the deserialization. This exception is used for some input problems, but in most cases, there should be more explicit subtypes to use.
Here MismatchedInpuException issue is happening because of type mismatch because passing JSON as an array of StudentDetail while deserialization is mapped for single StudentDetail object.
public class StudentDetail { private int rollNumber; private String firstName; private String lastName; //getter and setter of class }
import java.io.IOException; import com.fasterxml.jackson.databind.ObjectMapper; public class TestJacksonExample2 { public static void main(String[] args) { String json=" [" + "{"rollNumber":21 , "firstName":"Saurabh" , "lastName":"Gupta"}, " + "{"rollNumber":22 , "firstName":"Abhishek" , "lastName":"Garg"}" + "]"; System.out.println(json); try { ObjectMapper mapper = new ObjectMapper(); //issue is here StudentDetail student= mapper.readValue(json, StudentDetail.class); System.out.println(student); } catch(IOException ex) { ex.printStackTrace(); } catch(Exception ex) { ex.printStackTrace(); } } }
MismatchedInputException Stacktrace
[{"rollNumber":21 , "firstName":"Saurabh" , "lastName":"Gupta"}, {"rollNumber":22 , "firstName":"Abhishek" , "lastName":"Garg"}]
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.fiot.json.jackson.exceptions.StudentDetail` out of START_ARRAY token
at [Source: (String)" [{"rollNumber":21 , "firstName":"Saurabh" , "lastName":"Gupta"}, {"rollNumber":22 , "firstName":"Abhishek" , "lastName":"Garg"}]"; line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1139)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1093)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromArray(BeanDeserializerBase.java:1461)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:185)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
at com.fiot.json.jackson.exceptions.TestJacksonExample2.main(TestJacksonExample2.java:22)
Solutions
To resolve this issue, change the type from StudentDetail to as array StudentDetail[]
public static void main(String[] args) { String json=" [" + "{"rollNumber":21 , "firstName":"Saurabh" , "lastName":"Gupta"}, " + "{"rollNumber":22 , "firstName":"Abhishek" , "lastName":"Garg"}" + "]"; System.out.println(json); try { ObjectMapper mapper = new ObjectMapper(); //Convereted to Type as array StudentDetail[] students= mapper.readValue(json, StudentDetail[].class ); System.out.println(students); } catch(IOException ex) { ex.printStackTrace(); } catch(Exception ex) { ex.printStackTrace(); } }
References
https://fasterxml.github.io/jackson-databind/javadoc/2.9/com/fasterxml/jackson/databind/exc/MismatchedInputException.html
You would like to see
Follow below link to learn more on JSON and JSON issues solutions:
- JSON Tutorial
- JSON Issues Solutions
The problem
After the front end passes JSON format data to the back end, SpringMVC reports
org.springframework.http.converter.HttpMessageNotReadableException:
* JSON parse error: Can not deserialize instance of java.lang.String out of START_OBJECT token;
* nested exception is com.fasterxml.jackson.databind.JsonMappingException:
* Can not deserialize instance of java.lang.String out of START_OBJECT token
* at [Source: [email protected]; line: 1, column: 88] (through reference chain: com.xxx.XXXDto["employees"])
plan
To solve this problem, we can use one of the Uniform Exception Handling methods in Spring
@ExceptionHandler({HttpMessageNotReadableException.class, JsonMappingException.class, HttpMediaTypeNotSupportedException.class})
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String,Object> exceptionHandler(Exception ex){
Map<String,Object> map = new HashMap<>(3);
try{
map.put("code","400");
map.put("msg",ex.getMessage());
return map;
}catch (Exception e){
log.error("exception handler error",e);
map.put("code","400");
map.put("msg",e.getMessage());
return map;
}
}
Solve problems encountered in the process
The above method can handle the problem of JSON formatting errors, but the data content returned to the front end is in the following format
JSON parse error: Can not deserialize instance of java.lang.String out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token at [Source: [email protected]; line: 1, column: 88] (through reference chain: com.xxx.XXXDto["callBackUrl"])
We can’t see what the problem is at first sight, and even if we are familiar with the error, we can’t immediately find out where the problem is, because we need to process the above data and then send it back to the front end. Right
Finally solve the problem
We debug the source code found, Change is abnormal in springframework org. Springframework. HTTP. Converter. Json. AbstractJackson2HttpMessageConverter
thrown inside abnormal is
, Thrown in for springmvc
JsonMappingException extends JsonProcessingException HttpMessageNotReadableException
, as a result, we only need to add corresponding processing logic unified exception handling, can be returned to the front
@ExceptionHandler({HttpMessageNotReadableException.class, JsonMappingException.class, HttpMediaTypeNotSupportedException.class})
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String,Object> exceptionHandler(Exception ex){
Map<String,Object> map = new HashMap<>(3);
try{
if(ex instanceof HttpMessageNotReadableException
&& ex.getMessage().indexOf("JSON parse error:")>-1){
map.put("code","400");
String message=ex.getMessage();
int beginIndex=message.indexOf("XXXDto["");
int endIndex=message.indexOf(""])",beginIndex);
message="parameter"+message.substring(beginIndex+22,endIndex)+" format error";
map.put("msg",message);
}else{
map.put("code","400");
map.put("msg",ex.getMessage());
}
return map;
}catch (Exception e){
log.error("exception handler error",e);
map.put("code","400");
map.put("msg",e.getMessage());
return map;
}
}
Cannot deserialize instance of enum list spring boot exception
Issue
When you are trying to map the POST request body with enum properties, then you must need to do @JsonCreator to map the enums with request body and the list of properties available in the enum.
Full Exception for reference
JSON parse error: Cannot deserialize instance of ‘com.ngdeveloper.posts.enums.PostType’ out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of ‘com.ngdeveloper.posts.enums.PostType’ out of START_OBJECT token at [Source: (PushbackInputStream); line 17, column 5] (through reference chain: com.ngdeveloper.dto.posts”
Solution
Issue code for reference
@Getter @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum PostType { NEW("NEW","New Post"), DRAFT("DRAFT", "Drafted Post"); private String type; private String description; PostType(String type, String description){ this.type = type; this.description = description; } }
Fixed code for reference
Add the @JsonCreator annotation with the static method to map the json property with the enums.
@Getter @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum PostType { NEW("NEW","New Post"), DRAFT("DRAFT", "Drafted Post"); private String type; private String description; PostType(String type, String description){ this.type = type; this.description = description; } @JsonCreator static PostType findValue(@JsonProperty("type") String type, @JsonProperty("description") String description){ return Arrays.stream(PostType.values()).filter(pt -> pt.type.equlas(type) && pt.description.equals(description)).findFirst().get(); } }
Still “Cannot deserialize instance of enum list spring boot exception” comes ?
- Then you may need compare the exact value of the enums are matching with the request body.
- Do maven build and try once again!