wake-up-neo.com

Jackson: Serialisieren und deserialisieren Sie Enumerationswerte als Ganzzahlen

Betrachten Sie die folgende Enumeration und Klasse:

public enum State {
    ON,
    OFF,
    UNKNOWN
}

public class Machine {
    String name;
    int numCores;
    State state;

    public Machine(String name, int numCores, State state) {
        this.name = name;
        this.numCores = numCores;
        this.state = state;
    }
}

Und betrachten Sie die folgende Hauptfunktion:

public static void main(String args[]) {
    Machine m = new Machine("Machine 1", 8, OFF);
    ObjectMapper mapper = new ObjectMapper();
    String machineAsJsonString = mapper.writeValueAsString(m);
    System.out.println(machineAsJsonString);
}

Derzeit ist die Ausgabe dieses Hauptteils:

{"name" : "Machine 1", "numCores" : 8, "state" : "OFF"}

Diese Ausgabe ist nicht gut für mich, da ich anstelle der Zeichenfolge "OFF" für state1 verwenden möchte. Dies ist der Ordinalwert von OFF im Enum State

Das eigentliche Ergebnis, das ich erhalten möchte, ist:

{"name" : "Machine 1", "numCores" : 8, "state" : 1}

Gibt es eine elegante Möglichkeit, sich so zu verhalten?

15

Es sollte funktionieren, indem Sie JsonValue mapper angeben. 

public enum State {
    ON,
    OFF,
    UNKNOWN;

    @JsonValue
    public int toValue() {
        return ordinal();
    }
}  

Dies funktioniert auch für die Deserialisierung, wie in Javadoc der @JsonValue-Anmerkung angegeben:

HINWEIS: Bei Verwendung für Java-Enums ist der Wert .__ eine weitere Funktion. von annotierter Methode zurückgegeben wird auch als Wert für .__ betrachtet. Deserialize, nicht nur als JSON-String, als Serialisierung. Das ist möglich, da die Menge der Aufzählungswerte konstant ist und es möglich ist, Definieren Sie das Mapping, kann jedoch nicht generell für POJO-Typen ausgeführt werden. wie Dies wird also nicht zur POJO-Deserialisierung verwendet

31
user861594

Sie können die Einstellung verwenden 

objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);

Siehe https://github.com/FasterXML/jackson-databind/blob/master/src/test/Java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.Java für vollständige Testfälle

Vielen Dank an https://righele.it/2016/01/30/jackson-deserialization-von-json-nach-Java-enums/

9
Martin

Sie können auf diese Weise verwenden

import com.fasterxml.jackson.annotation.JsonFormat;

@JsonFormat(shape = JsonFormat.Shape.NUMBER)
public enum State {
       ON,
       OFF,
       UNKNOWN
}
2
dasunse

Wenn Sie die Ordnungszahl der Aufzählung drucken möchten, können Sie Ihren Konstruktor so ändern, dass er ein int anstelle von State akzeptiert. Anschließend können Sie ihn in Ihrem Aufruf an Machine strukturieren folgenden Weg:

Machine m = new Machine("Machine 1", 8, State.OFF.ordinal());

Dadurch wird der Ordnungszahlwert des übergebenen Zustands abgerufen und Folgendes ausgegeben

{name='Machine 1', numCores=8, state=1}

2
Tom C

Zur Vervollständigung poste ich einen anderen Weg: benutzerdefinierte Serialisierer:

public class StateSerializer extends JsonSerializer<State> {  
    public void serialize(State value, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException {
        generator.writeStartObject();
        generator.writeFieldName("id");
        generator.writeNumber(value.getId());
        generator.writeEndObject();
    }
}

@JsonSerialize(using = StateSerializer.class)
public enum State { 
    ...
    public int getId(){...}
}
1
Paco Abato

Noch ein anderer Weg: 

public enum State {

    @JsonProperty("0")
    ON,

    @JsonProperty("1")
    OFF,

    @JsonProperty("2")
    UNKNOWN
}

Dies erzeugt jedoch {"state" : "1"} anstelle von {"state" : 1} (Zeichenfolge, nicht numerisch). In den meisten Fällen ist es OK

0