Reputation: 864
I am getting the following JSON as response from a service. I am using Spring RestTemplate to call the service which also deserializes the JSON back into an Object. I am trying to deserialize it into an Object that has a List besides other fields. I am getting the following error while deserializing:
Can not instantiate value of type [simple type, class com.org.EmployeeInfo] from String value; no single-String constructor/factory method.
Following is the JSON that i want to deserialize:
{
"employees": {
"employeeInfo": [
"{\r\n \"id\": \"123\",\r\n \"group\": \"MARKETING\",\r\n \"role\": \"MANAGER\",\r\n}",
"{\r\n \"id\": \"256\",\r\n \"group\": \"IT\",\r\n \"role\": \"DIRECTOR\",\r\n}",
"{\r\n \"id\": \"789\",\r\n \"group\": \"SALES\",\r\n \"role\": \"CEO\",\r\n}"
]
},
"status": "EMPLOYED",
"somethingElse": {
"something": []
}
}
The default deserializer fails if i have the List<EmployeeInfo>
in the object that i try to map the respone to, but it works if i use List<String>
or String[]
. This is because of the double quotes in the JSON (I am talking about "{\r\n) which makes it treat as a String
I am planning to write a custom deserializer to deserialize it into an object having List and also remove the \r\n that's part of the response. How can i do that? Appreciate any responses.
Here are my POJOs:
public class Response {
private Employees employees;
private String status;
private SomethingElse somethingElse;
// getters, setters
}
public class Employees {
List<EmployeeInfo> employeeInfo;
// getters, setters
}
public class EmployeeInfo
{
private String id, group, role;
// getters, setters
}
Thanks
Upvotes: 0
Views: 5722
Reputation: 864
I worked around this problem in the following way (some of the logic needs to be optimized)
public class EmployeeInfoJsonDeserializer extends JsonDeserializer<List<EmployeeInfo>> {
@Override
public List<EmployeeInfo> deserialize(final JsonParser jp, final DeserializationContext ctxt)
throws IOException, JsonProcessingException {
final ObjectMapper mapper = (ObjectMapper) jp.getCodec();
final JsonNode node = (JsonNode) mapper.readTree(jp);
// TODO - Write the following logic in a better way
String toStr = node.toString();
toStr = StringUtils.replace(toStr, "\"{", "{");
toStr = StringUtils.replace(toStr, "}\"", "}");
toStr = StringUtils.remove(toStr, "\\r\\n");
toStr = StringUtils.remove(toStr, "\\");
final JsonNode newNode = mapper.readTree(toStr);
final EmployeeInfo[] empInfo = mapper.convertValue(newNode, EmployeeInfo[].class);
return Arrays.asList(empInfo);
}
}
In the Pojo:
public class Employees {
List<EmployeeInfo> employeeInfo;
public List<EmployeeInfo> getEmployeeInfo() {
return employeeInfo;
}
@JsonDeserialize(using = EmployeeInfoJsonDeserializer .class)
public void setEmployeeInfo(final List<EmployeeInfo> employeeInfo) {
this.employeeInfo= employeeInfo;
}
}
Upvotes: 4
Reputation: 10404
That JSON is unparseable because is not valid, you can not deserialize it even if you have a custom deserializer.
Anyway, a custom deserializer example (does not work, is for learning purpouses only)
public class EmployeeInfoDeSerializer extends JsonDeserializer<List<EmployeeInfo>> {
@Override
public List<EmployeeInfo> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
// for learning purpouses only, does not work
ObjectMapper mapper = new ObjectMapper();
mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
List<EmployeeInfo> employeeInfos = new ArrayList<>();
while (jp.nextToken() != JsonToken.END_OBJECT) {
if (jp.getCurrentToken() != JsonToken.END_ARRAY) {
JsonParser jParser = mapper.getJsonFactory().createJsonParser(jp.getText());
employeeInfos.add(jParser.readValueAs(EmployeeInfo.class));
}
}
return employeeInfos;
}
}
in your Employees class
public class Employees {
@JsonDeserialize(using=EmployeeInfoDeSerializer.class)
private List<EmployeeInfo> employeeInfo;
public List<EmployeeInfo> getEmployeeInfo() {
return employeeInfo;
}
public void setEmployeeInfo(List<EmployeeInfo> employeeInfo) {
this.employeeInfo = employeeInfo;
}
}
Upvotes: 0