I have a lib which i cannot change.
This lib has api method which returns json like this {OrderStatus=PartiallyFilledCanceled}
and also this lib has a enum
@AllArgsConstructor
public enum OrderStatus {
PARTIALLY_FILLED_CANCELED("PartiallyFilledCanceled");
private final String description;
}
and dto with OrderStatus field.
So I got an error
java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.api.client.domain.OrderStatus` from String "PartiallyFilledCanceled": not one of the values accepted for Enum class:[PARTIALLY_FILLED_CANCELED]
My ObjectMapper configs:
objectMapper.registerModule(new JavaTimeModule());
objectMapper.enable(JsonParser.Feature.IGNORE_UNDEFINED);
objectMapper.coercionConfigFor(LogicalType.Enum).setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsNull);
How can I use some custom deserializer without changing dto?
You need to iterate the possible values and pick the one with matching description.
public class OrderStatusDeserializer extends StdDeserializer<OrderStatus> {
public OrderStatusDeserializer() {
super(OrderStatus.class);
}
@Override
public OrderStatus deserialize(JsonParser parser, DeserializationContext context) throws IOException {
JsonNode node = parser.readValueAsTree();
String value = node.textValue();
for (OrderStatus orderStatus : OrderStatus.values()) {
if (orderStatus.getDescription().equals(value)) {
return orderStatus;
}
}
//description was not found, handle according to needs
throw new InvalidFormatException(parser, "Description not found", value, _valueClass);
}
}
Register the deserializer directly with ObjectMapper
:
ObjectMapper mapper = new ObjectMapper();
SimpleModule myModule = new SimpleModule();
myModule.addDeserializer(OrderStatus.class, new OrderStatusDeserializer());
mapper.registerModule(myModule);