Jackson - deserialize one base enums

2020-06-01 03:31发布

is it possible to deserialize enums, which have a one based index?

enum Status {
  Active,
  Inactive
}

{status:1} means Status.Active, but Jackson makes it Status.Inactive :(

3条回答
够拽才男人
2楼-- · 2020-06-01 03:49

Enums have numeric ordinals, starting in zero, and get assigned to each value in an enumeration in the order in which they were declared. For example, in your code Active has ordinal 0 and Inactive has ordinal 1. You can go back and forth between the value of an enum and its ordinal, like this:

// 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];

Clearly the ordinal 1 corresponds to Inactive (it's not a Jackson problem), as explained above, ordinals in an enumeration are zero-based. Maybe you should fix your code to reflect that, and make sure that {status:0} means Status.Active.

查看更多
聊天终结者
3楼-- · 2020-06-01 03:54
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);        

}}
查看更多
迷人小祖宗
4楼-- · 2020-06-01 04:07

You can create a custom type deserialiser for your enum:

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

You can then tell Jackson to use your custom deserialiser for a property:

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

You can also configure the Jackson object mapper to use your custom deserialiser for all occurrences of the target type. See http://wiki.fasterxml.com/JacksonHowToCustomDeserializers.

查看更多
登录 后发表回答