@Data
@NoArgsConstructor
@AllArgsConstructor
public class MatchingResponse {
@JsonProperty(value = "Code")
private String code;
@JsonProperty(value = "Msg")
private String message;
@JsonProperty(value = "Id")
private int id;
@JsonProperty(value = "Date")
private String date;
@JsonProperty(value = "ClientIin")
private String clientIin;
@JsonProperty(value = "Similarity")
private String similarity;
@JsonProperty(value = "VendorName")
private String vendorName;
}
This is my class. I`m trying to deserialize this JSON:
{
"Code": "200",
"Msg": "",
"Id": 20148,
"Date": "2023-08-01T15:21:13.9704572+06:00",
"ClientIin": "888888888888",
"Similarity": "0.007720462",
"VendorName": "SomeName"
}
to my custom class with this code:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
byte[] byteResponse = httpResponse.getEntity().getContent().readAllBytes();
MatchingResponse response = mapper.readValue(byteResponse, MatchingResponse.class);
but because of JSON has empty variable "Msg", I`m getting exception:
Cannot construct instance of `MatchingResponse` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"Code":"200","Msg":"","Id":20148,"Date":"2023-08-01T15:18:03.883337+06:00","ClientIin":"888888888888","Similarity":"0.0738383234","VendorName":"SomeName"}')
at [Source: (byte[])""{"Code":"200","Msg":"","Id":20147,"Date":"2023-08-01T15:18:03.883337+06:00","ClientIin":"830921301593","Similarity":"0.0738383234","VendorName":"VisionLabs"}""; line: 1, column: 1]
I tried creating JsonSetter:
@JsonSetter
public void setMessage(String message) {
if (message != null && message.isEmpty()) {
this.message = null;
} else {
this.message = message;
}
}
like this or tried creating deserializers:
public class MatchingResponseDeserializer extends StdDeserializer<MatchingResponse> {
public MatchingResponseDeserializer() {
this(null);
}
public MatchingResponseDeserializer(Class<?> vc) {
super(vc);
}
@Override
public MatchingResponse deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
String code = getOptionalString(node, "Code");
String message = getOptionalString(node, "Msg");
int id = getOptionalInt(node, "Id");
String date = getOptionalString(node, "Date");
String clientIin = getOptionalString(node, "ClientIin");
String similarity = getOptionalString(node, "Similarity");
String vendorName = getOptionalString(node, "VendorName");
return new MatchingResponse(code, message, id, date, clientIin, similarity, vendorName);
}
private String getOptionalString(JsonNode node, String fieldName) {
JsonNode valueNode = node.get(fieldName);
return (valueNode != null) ? valueNode.asText() : null;
}
private int getOptionalInt(JsonNode node, String fieldName) {
JsonNode valueNode = node.get(fieldName);
return (valueNode != null) ? valueNode.asInt() : 0; // Provide a default value if needed
}
}
Set this deserializer to the class:
@JsonDeserialize(using = MatchingResponseDeserializer.class)
public class MatchingResponse {
This deserializer:
public class EmptyStringDeserializer extends JsonDeserializer<String> {
public EmptyStringDeserializer() {
this(null);
}
public EmptyStringDeserializer(Class<?> vc) {
super(vc);
}
@Override
public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
JsonNode node = jsonParser.readValueAsTree();
if (node.asText().isEmpty()) {
return null;
}
return node.toString();
}
}
I set to variable:
@JsonProperty(value = "Msg")
@JsonDeserialize(using = EmptyStringDeserializer.class)
private String message;
but none of it worked.
I tried use Gson, but get exception:
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 2 path $
So my question is, how can I fix this error? How to work with empty JSON variables?
3
Answers
You can try:
The mapper.readTree(jsonString) parses the string into a JsonNode, which is Jackson’s tree model for
JSON.mapper.treeToValue(rootNode, MatchingResponse.class)
then converts this tree into your object.Also, you don’t need to enable
DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT
. Jackson automatically converts empty strings in the JSON to empty strings in the object, not null.Why don’t you try using json as jsonString and use
instead of byte[]
try removing
@AllArgsConstructor
, a small test without Lombok works fine…I guess there’s some issue with missing
@JsonCreator
annotation on the constructor generated by Lombok.