Джексон: Сериализовать и десериализовать значения enum как целые числа
Рассмотрим следующее перечисление и класс:
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;
}
}
И рассмотрим следующую основную функцию:
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);
}
В настоящее время вывод этого основного файла:
{"name" : "Machine 1", "numCores" : 8, "state" : "OFF"}
Этот вывод не подходит для меня, так как вместо строки "OFF"
для state
я хотел бы, чтобы это было 1
, которое является порядковым значением OFF
в перечислении state
.
Итак, фактический результат, который я хочу получить, это:
{"name" : "Machine 1", "numCores" : 8, "state" : 1}
Есть ли элегантный способ заставить его вести себя таким образом?
Ответы
Ответ 1
Он должен работать, указав JsonValue
mapper.
public enum State {
ON,
OFF,
UNKNOWN;
@JsonValue
public int toValue() {
return ordinal();
}
}
Это также работает для десериализации, как отмечено в Javadoc @JsonValue
аннотации:
ПРИМЕЧАНИЕ. При использовании для перечислений Java одна дополнительная функция - это значение возвращаемый аннотированным методом, также считается значением десериализуем, а не только строку JSON для сериализации как. Это возможно, поскольку множество значений Enum является постоянным, и можно определить отображение, но не может быть сделано вообще для типов POJO; в виде такой, это не используется для десериализации POJO
Ответ 2
Вы можете использовать настройки
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);
См. Https://github.com/FasterXML/jackson-databind/blob/master/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java для полного тестирования
Благодаря подсказке на https://righele.it/2016/01/30/jackson-deserialization-from-json-to-java-enums/
Ответ 3
Если вы хотите напечатать порядковый номер перечисления, вы можете изменить свой конструктор, чтобы принять int
вместо State
, а затем в своем обращении к Machine
вы можете его структурировать следующим образом:
Machine m = new Machine("Machine 1", 8, State.OFF.ordinal());
Это получит порядковое значение enum переданного состояния и напечатает следующие
{name='Machine 1', numCores=8, state=1}
Ответ 4
Для завершения я отправляю другой способ: пользовательский сериализатор:
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(){...}
}
Ответ 5
Еще один способ:
public enum State {
@JsonProperty("0")
ON,
@JsonProperty("1")
OFF,
@JsonProperty("2")
UNKNOWN
}
Тем не менее, это будет производить {"state": "1"}
вместо {"state": 1}
(строка, а не число). В большинстве случаев это нормально
Ответ 6
Вы можете использовать таким образом
import com.fasterxml.jackson.annotation.JsonFormat;
@JsonFormat(shape = JsonFormat.Shape.NUMBER)
public enum State {
ON,
OFF,
UNKNOWN
}