Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson deserialization error: no String-argument constructor/factory method to deserialize from String value

I am trying to deserialize the following JSON

{
  "deliverLumpSum": 0.0,
  "faxQId": "{\"type\":\"TAKEAWAY\",\"data\":{\"orderId\":\"AWSWD-AWSAW\",\"orderKey\":\"DERS34S32SD\"}}"
}

With help of the following custom deserializer

public class OrderIdDeserializer extends JsonDeserializer<OrderId> {

  @Override
  public OrderId deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
      OrderId orderId = jsonParser.readValueAs(OrderId.class);
      return orderId;
  }
}

into the following object-structure

@Data
public class AddInfo {

  protected double deliverLumpSum;
  
  @JsonDeserialize( using = OrderIdDeserializer.class)
  public OrderId orderId;

}

@Data
public class OrderId {

  private String type;
  private TakeawayData data;

}

@Data
public class TakeawayData {

  private String orderId;
  private String orderKey;

}

I get the following error

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of OrderId (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"type":"TAKEAWAY","data":{"orderId":"AWSWD-AWSAW","orderKey":"DERS34S32SD"}}')

What am I doing wrong and how can I solve this problem?

like image 349
user1167253 Avatar asked Oct 30 '18 23:10

user1167253


1 Answers

First, your JSON example ("faxQId":) doesn't match your Java class AddInfo:

@JsonDeserialize( using = OrderIdDeserializer.class)
public OrderId orderId;

I guess this is just a copy-and-paste error and you really mean

@JsonDeserialize( using = OrderIdDeserializer.class)
public OrderId faxQId;

Now for the real problem. Your JSON content after "faxQId": has a JSON string containing JSON code (with properly escaped " quotes)

"faxQId": "{\"type\":\"TAKEAWAY\",\"data\":{\"orderId\":\"AWSWD-AWSAW\",\"orderKey\":\"DERS34S32SD\"}}"

instead of just a normal JSON object like

"faxQId": {"type":"TAKEAWAY","data":{"orderId":"AWSWD-AWSAW","orderKey":"DERS34S32SD"}}"

Therefore, in your deserializer you need an additional step for deserializing this String to a Java object.

public class OrderIdDeserializer extends JsonDeserializer<OrderId> {

  @Override
  public OrderId deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {

    // Get the JSON text (with the \ already decoded):
    // {"type":"TAKEAWAY","data":{"orderId":"AWSWD-AWSAW","orderKey":"DERS34S32SD"}}
    String s = jsonParser.getValueAsString();
      
    // We need a second parser for deserializing the JSON text
    JsonParser jsonParser2 = jsonParser.getCodec().getFactory().createParser(s);

    // Convert the JSON text into an object
    return jsonParser2.readValueAs(OrderId.class);
  }
}
like image 100
Thomas Fritsch Avatar answered Oct 25 '22 12:10

Thomas Fritsch