Java - Parse enum from api by text description

33 Views Asked by At

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?

1

There are 1 best solutions below

0
Chaosfire On BEST ANSWER

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);