Reputation: 21
I wonder why spring boot can deserialize the class which has no default constructor by Jackson's objectMapper,but when i mannually using objectMapper in unit test,it can not deserialize(com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of xxx
(no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
).
Here is my controller:
@PostMapping("/precise")
public Resp<List<MatchedOutLineResponseDTO>> getPreciseMatchedOutLine(
@RequestBody List<MatchedOutLineRequestDTO> request)
Here is my pojo:
@Getter
public class MatchedOutLineRequestDTO {
private String uuid;
private JSONObject outLineGeometry;
public MatchedOutLineRequestDTO(String uuid, JSONObject outLineGeometry) {
this.uuid = uuid;
this.outLineGeometry = outLineGeometry;
}
}
can someone tell me the reason?
Upvotes: 1
Views: 4321
Reputation: 322
get...
) for properties you want to exposeConsider the code example below
public class Test {
@Getter
static class Dummy {
private String uuid;
private Date date;
private JSONObject jsonObject;
public Dummy(String uuid, Date date, JSONObject jsonObject) {
this.uuid = uuid;
this.date = date;
this.jsonObject = jsonObject;
}
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
JSONObject jsonObject = new JSONObject();
jsonObject.put("Name", "John Doe");
jsonObject.put("Age", "Unknown");
Dummy dummyObj = new Dummy(UUID.randomUUID().toString(), new Date(), jsonObject);
String jsonStr = mapper.writeValueAsString(dummyObj);
System.out.println("Serialized JSON = " + jsonStr);
}
}
If you run this code, the only serialization error you will get is No serializer found for class org.json.JSONObject
The problem is the serialization of the JSONObject
class.
The default configuration of ObjectMapper instance is to only access properties that are public fields or have public getters.
Hence this is problem in serialization of org.json.JSONObject
.
There can be few workarounds
Remove JsonObject
and use a Map
instead.
Configure your object mapper to access Private fields by adding this:
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
You will see the output like this
{
"uuid": "15f37c75-9a82-476b-a725-90f3742d3de1",
"date": 1607961986243,
"jsonObject": {
"map": {
"Age": "Unknown",
"Name": "John Doe"
}
}
}
Last option is to ignore failing fields (like JSONObject
) and serialize remaining fields. You can do this by configuring the object mapper like this:
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
If you do this you will see output like this below:
{
"uuid": "82808d07-47eb-4f56-85ff-7a788158bbb5",
"date": 1607962486862,
"jsonObject": {}
}
Upvotes: 4