首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Jackson不能将enum反序列化为对象,即使我添加了自定义反序列化器。

Jackson不能将enum反序列化为对象,即使我添加了自定义反序列化器。
EN

Stack Overflow用户
提问于 2015-04-10 16:19:00
回答 1查看 9.5K关注 0票数 5

我想使用Jackson JSON来序列化/反序列化包含枚举对象的类。我的课是:

代码语言:javascript
运行
复制
class Bar {

    @JsonProperty("rateType")
    @JsonDeserialize(using = ReturnedRateTypeDeserializer.class)
    private ReturnedRateType rateType;

    public ReturnedRateType getRateType() {
        return rateType;
    }

    public void setRateType(ReturnedRateType rateType) {
        this.rateType = rateType;
    }
}

枚举类ReturnedRateType定义为:

代码语言:javascript
运行
复制
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum ReturnedRateType {
    AA("AA"),
    BB("BB"),
    CC("CC");

    @JsonProperty("value")
    private String value;

    ReturnedRateType(String value) {
        this.value = value;
    }

    @JsonCreator
    public static ReturnedRateType fromValue(final String value) {
        if (value != null) {
            for (ReturnedRateType type : ReturnedRateType.values()) {
                if (value.equalsIgnoreCase(type.value)) {
                    return type;
                }
            }
        }
        return null;
    }
}

正如您所看到的,我添加了@JsonFormat注释来告诉杰克逊将这个枚举序列化为POJO,并添加了@JsonCreator注释以从给定的字符串获得一个静态工厂方法到枚举对象。由于Jackson只能序列化而不能从对象表示反序列化到枚举,所以我为枚举ReturnedRateType添加了以下自定义反序列化器

代码语言:javascript
运行
复制
public class ReturnedRateTypeDeserializer extends JsonDeserializer<ReturnedRateType> {

    @Override
    public ReturnedRateType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ReturnedRateType type = ReturnedRateType.fromValue(jp.getValueAsString());
        if(type != null)
            return type;
        throw new JsonMappingException("invalid value for ReturnedRateType");
    }
} 

但是,当我测试从JSON字符串到enum的反序列化时,我得到了错误。JSON字符串是:

代码语言:javascript
运行
复制
{"rateType": {"value": "AA"}}

我的测试代码是:

代码语言:javascript
运行
复制
@Test
public void RateTypeToEnum() {
    String json = "{\"rateType\": {\"value\": \"AA\"}}";
    System.out.println(json);
    ObjectMapper mapper = new ObjectMapper();
    Bar bar = null;
    try {
        bar = mapper.readValue(json, Bar.class);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println(bar.getRateType());
}

我希望看到输出应该是AA。但是,在执行过程中,自定义反序列化程序jp.getValueAsString()中的ReturnedRateTypeDeserializer为null:

代码语言:javascript
运行
复制
ReturnedRateType type = ReturnedRateType.fromValue(jp.getValueAsString());  //jp.getValueAsString() is null here!

因此,它返回错误。那么这里出了什么问题?

EN

回答 1

Stack Overflow用户

发布于 2015-04-11 19:14:52

根据杰克逊关于2.5.X注释的JsonFormat文档,Shape.Object不适用于枚举反序列化:

  • Enum:形状JsonFormat.Shape.STRING和JsonFormat.Shape.NUMBER可用于在数字(索引)和文本(名称或toString())之间进行更改;但也可以使用JsonFormat.Shape.OBJECT来序列化(而不是反序列化)。

我会让JsonCreator静态方法接受一个JsonNode并从中读取字符串值。

注意,这在2.5.X之后就能工作了。在早期版本中,您需要编写自定义反序列化器。下面是一个示例:

代码语言:javascript
运行
复制
public class JacksonEnumObjectShape {
    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
    @JsonDeserialize(using = ReturnedRateTypeDeserializer.class)
    public enum ReturnedRateType {
        AA("AA"),
        BB("BB"),
        CC("CC");

        @JsonProperty("value")
        private String value;

        ReturnedRateType(String value) {
            this.value = value;
        }

        @JsonCreator
        public static ReturnedRateType fromValue(final JsonNode jsonNode) {

            for (ReturnedRateType type : ReturnedRateType.values()) {
                if (type.value.equals(jsonNode.get("value").asText())) {
                    return type;
                }
            }
            return null;
        }
    }
    // can be avoided since 2.5
    public static class ReturnedRateTypeDeserializer extends JsonDeserializer<ReturnedRateType> {

        @Override
        public ReturnedRateType deserialize(
                final JsonParser jp,
                final DeserializationContext ctxt) throws IOException {
            final JsonNode jsonNode = jp.readValueAsTree();
            return ReturnedRateType.fromValue(jsonNode);
        }
    }

    public static void main(String[] args) throws IOException {
        final ObjectMapper mapper = new ObjectMapper();
        final String json = mapper.writeValueAsString(ReturnedRateType.AA);
        System.out.println(json);
        System.out.println(mapper.readValue(json, ReturnedRateType.class));
    }
}

输出:

代码语言:javascript
运行
复制
{"value":"AA"}
AA
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29566177

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档