Можно ли десериализовать перечисления, которые имеют один индекс?Jackson - десериализовать одну базовую enums
enum Status {
Active,
Inactive
}
{Статус: 1} означает Status.Active, но Джексон делает его Status.Inactive :(
Можно ли десериализовать перечисления, которые имеют один индекс?Jackson - десериализовать одну базовую enums
enum Status {
Active,
Inactive
}
{Статус: 1} означает Status.Active, но Джексон делает его Status.Inactive :(
Вы можете создать пользовательский тип deserialiser для перечисления:
public enum Status {
ACTIVE,
INACTIVE;
public static Status fromTypeCode(final int typeCode) {
switch(typeCode) {
case 1: return ACTIVE;
case 2: return INACTIVE;
}
throw new IllegalArgumentException("Invalid Status type code: " + typeCode);
}
}
public class StatusDeserializer extends JsonDeserializer<Status> {
@Override
public Status deserialize(final JsonParser parser, final DeserializationContext context) throws IOException {
return Status.fromTypeCode(parser.getValueAsInt());
}
}
Вы можете сказать Джексон использовать пользовательские deserialiser для свойства:
public class WarpDrive {
private Status status;
@JsonDeserialize(using = StatusDeserializer.class)
public void setStatus(final Status status) {
this.status = status;
}
public Status getStatus() {
return this.status;
}
}
Вы также можете настроить объект Джексона mapper, чтобы использовать свой десериализатор для всех вхождений целевого типа. См. http://wiki.fasterxml.com/JacksonHowToCustomDeserializers.
Перечни имеют числовые порядковые, начиная с нуля, и получить присваивается каждому значению в перечислении . в том порядке, в котором они были объявлены, например, в коде Active
имеет порядковый номер 0
и Inactive
имеют порядковый 1
Вы можете вернуться назад и вперед между значением перечисления и его порядковым номером, например:.
// ordinal=0, since Active was declared first in the enum
int ordinal = Status.Active.ordinal();
// enumVal=Active, since 0 is the ordinal corresponding to Active
Status enumVal = Status.values()[0];
Очевидно, что порядковый номер 1
соответствует Inactive
(это не проблема Джексона), как объяснялось выше, ординалы в перечислении основаны на нуле. Возможно, вы должны исправить свой код, чтобы это отразить, и убедитесь, что {status:0}
означает Status.Active
.
Его ясно, что 0 означает Status.Active в мире java! Но это не мой api, я только реализую клиента. И api говорит, что 1 означает Active и 2 Inactive. Так что мой вопрос был, если я могу рассказать об этом Джексону. Возможно, просто добавив фиктивное значение для смещения ординала на единицу. – Dirk
Не рекомендуется использовать порядковые номера Enum, а тем более использовать их в сериализации, поскольку изменения в определении Enum могут изменять порядковые номера. – florian
public enum Status {
ACTIVE(1),
INACTIVE(2);
private final int value;
Status(int v) {
value = v;
}
@org.codehaus.jackson.annotate.JsonValue
public int value() {
return value;
}
@org.codehaus.jackson.annotate.JsonCreator
public static Status fromValue(int typeCode) {
for (Status c: Status.values()) {
if (c.value==typeCode) {
return c;
}
}
throw new IllegalArgumentException("Invalid Status type code: " + typeCode);
}}
Это на самом деле более простое, более идиоматическое решение, чем мое. Спасибо, что поделился. – Nathan
Это также отличный способ справиться с общей проблемой перечисления сериализуемых данных с неизвестной капитализацией. –
но если перечисление является третьим лицом? – gstackoverflow
вопрос не имеет ничего общего с сериализации –
Как Оскар говорит, перечисление (и информатики в целом) является 0 на основе. Вычитайте 1 из числа, если это то, что вы получаете от другого слоя. – rynmrtn