首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从JSON反序列化java枚举

从JSON反序列化java枚举
EN

Stack Overflow用户
提问于 2013-08-29 15:49:18
回答 2查看 37.3K关注 0票数 4

我们使用Jackson 1.9.1来序列化和反序列化进出Java对象的JSON请求响应字符串。原始Java类型、集合类型和自定义对象被(反)序列化,没有问题。但是,我在尝试将JSON字符串反序列化为java枚举时遇到了问题。JSON字符串的序列化方式如下:

代码语言:javascript
复制
"wt":{"wt":100.5,"unit":{"LBS":3}}

wt的Java类型如下所示:

代码语言:javascript
复制
public class Weight {

    protected double weight;
    protected Unit unit;
}

我参考了thisthisthis,并提出了权重单位的枚举,如下所示:

代码语言:javascript
复制
public enum Unit {

    KG("kg"),
    GM("gm"),
    LBS("lbs"),
    OZ("oz");

    private String value;  
    private WeightMeasurementUnit(String value) { this.value = value; }

    @JsonValue
    public String getValue() { return this.value; }

    @JsonCreator
    public static Unit create(String val) {
        Unit[] units = Unit.values();
        for (Unit unit : units) {
            if (unit.getValue().equals(val)) {
                return unit;
            }
        }
        return LBS;
    }
}

问题是,当我试图反序列化上面提到的JSON时,我得到这样的错误:“无法识别的字段"LBS”(类a.b.c.d.Weight),未标记为可忽略“异常堆栈跟踪是这样的:

代码语言:javascript
复制
Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "LBS" (Class a.b.c.d.Weight), not marked as ignorable
 at [Source: java.io.ByteArrayInputStream@20172017; line: 1, column: 464] (through reference chain: a.b.c.d.MyRequest["blah"]->a.b.c.d.AnotherType["wt"]->a.b.c.d.Weight["LBS"])
    at org.codehaus.jackson.map.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:53)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:267)
    at org.codehaus.jackson.map.deser.std.StdDeserializer.reportUnknownProperty(StdDeserializer.java:673)
    at org.codehaus.jackson.map.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:659)
    at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:1365)

..。

我的问题是:枚举的序列化JSON字符串是否正确?为了正确地反序列化枚举,我还应该包括(或注释)什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-29 16:32:25

我假设在public enum Unit代码块中,您指的是Unit而不是WeightMeasurementUnit

Weight类只有一个weight和一个unit,所以如果您传递{"wt":100.5,"unit":"lbs"},它应该可以工作,因为unit只是一个没有值的单元。因此,反序列化程序无法将{"LBS":3}解析为Unit3是用来做什么的?

另一个问题是,你的值是"LBS“,而你传递的是"lbs”。所以要么你需要标准化,要么你需要使用unit.getValue().equalsIgnoreCase(val)

票数 6
EN

Stack Overflow用户

发布于 2015-12-23 21:06:07

我建议你更新你的杰克逊版本到2.7.0-rc2 (也可能更早),然后配置ObjectMapper,如下所示:

代码语言:javascript
复制
private ObjectMapper createObjectMapper() {
    final ObjectMapper mapper = new ObjectMapper();
    // enable toString method of enums to return the value to be mapped
    mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
    mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
    return mapper;
}

在枚举中,您只需覆盖toString()方法:

代码语言:javascript
复制
public enum Unit {
    KG,
    GM,
    LBS,
    OZ;

    // UPDATE: implicitly already the default so override not needed in this case
    @Override
    public String toString() {
        return name();
    }
}

您不需要任何注释或自定义的反序列化程序。这将是将一个简单的枚举映射到一个json的方法,反之亦然。

如果您的枚举应该从一个特殊字符串映射,则必须添加一个值字段和一个构造函数,该构造函数分配此字段并在toString方法中返回值。

代码语言:javascript
复制
public enum Unit {
    KG("kilogram"),
    GM("gram"),
    LBS("blah"),
    OZ("anything");

    Unit(final String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return value;
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18505102

复制
相关文章

相似问题

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