2017-12-23 10 views
3

Nehmen wir an, ich habe eine enum Status, die so aussieht.Jackson deserialize verschiedene Saiten auf die gleiche Enum-Konstante

public enum Status { 
    SUCCESS, 
    FAIL, 
    RETRY, 
    UNKNOWN 
} 

Ich erhalte status Eigenschaft aus einer JSON, die wie folgende Beispiele aussehen könnte.

  • {"status":"success"} // gültig Fall deserialisieren zu Status.SUCCESS
  • {"status":"fail"} // gültig Fall deserialisieren zu Status.FAIL
  • {"status":"retry"} // gültig Fall deserialisieren zu Status.RETRY

Aber jeder andere Wert sollte auf Status.UNKNOWN deserialisiert werden. Beispiele.

  • {"status":"blabla"} // ungültig Fall deserialisieren zu Status.UNKNOWN
  • {"status":"John"} // ungültig Fall deserialisieren zu Status.UNKNOWN

Ich weiß, dass ich es durch das Schreiben eines benutzerdefinierten Deserializer tun könnte, aber ich würde versuchen, Um das zu vermeiden, weil ich viele, viele enums in meinem Programm habe und einen eigenen Deserializer für jeden von ihnen benötige, wäre das ein Overkill.

Idealerweise eine Art Konstruktor aus Regex, der mit einer beliebigen Zeichenfolge übereinstimmt (außer "success", "fail" und "retry").

Gibt es eine Möglichkeit, es mit Jackson zu tun, ohne Custom Deserializer zu schreiben?

Antwort

1

Wenn alle Ihre Aufzählungen UNKNOWN Wert haben, können Sie eine benutzerdefinierte Deserializer wie folgt schreiben:

class EnumDeserializer extends JsonDeserializer<Enum> { 

    private final Class<? extends Enum> enumType; 

    public EnumDeserializer(Class<? extends Enum> enumType) { 
     this.enumType = enumType; 
    } 

    @Override 
    public Enum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { 
     try { 
      String stringValue = jp.getValueAsString().toUpperCase(); 
      return Enum.valueOf(enumType, stringValue.toUpperCase()); 
     } catch (IllegalArgumentException e) { 
      return Enum.valueOf(enumType, "UNKNOWN"); 
     } 
    } 
} 

und konfigurieren Sie Ihre Mapper Benutzer es:

SimpleModule module = new SimpleModule(); 
module.setDeserializerModifier(new BeanDeserializerModifier() { 
    @Override 
    public JsonDeserializer<Enum> modifyEnumDeserializer(DeserializationConfig config, 
                 final JavaType type, 
                 BeanDescription beanDesc, 
                 final JsonDeserializer<?> deserializer) { 

     return new EnumDeserializer((Class<Enum<?>>) type.getRawClass()); 
    } 
}); 

ObjectMapper mapper = new ObjectMapper(); 
mapper.registerModule(module); 

Alternativ können Sie jackson Deserialisierung verwenden Feature zum Einstellen des Standardwertes für unbekannte Enum-Eigenschaften:

Aber mit diesem Ansatz müssen Sie alle Ihre Enums ändern, um @JsonEnumDefaultValue Annotation für den Standardwert zu verwenden, und standardmäßig behandelt es keine Enumerationswerte in Kleinbuchstaben.

+0

Könnte ich fragen, wie Sie diese Frage herausfinden? Ich habe zwei Tage damit verbracht, den Quellcode von jackson-databind zu finden, aber nichts gefunden .... – LoveTW

Verwandte Themen