简体   繁体   English

从JSON反序列化java枚举

[英]Deserialize java enum from JSON

We use Jackson 1.9.1 to serialize and deserialize JSON request response strings to/from Java objects. 我们使用Jackson 1.9.1对JSON请求响应字符串进行序列化和反序列化。 Primitive Java types, collection types, and custom objects are (de)serialized without issues. 原始Java类型,集合类型和自定义对象(序列化)没有问题。 However, I have a problem trying to deserialize JSON string into java enum. 但是,我在尝试将JSON字符串反序列化为java枚举时遇到问题。 JSON string is serialized like so: JSON字符串是这样序列化的:

"wt":{"wt":100.5,"unit":{"LBS":3}}

Java type for wt is like so: wt的Java类型是这样的:

public class Weight {

    protected double weight;
    protected Unit unit;
}

I referred to this , this , and this on SO and came up with enum for weight units like so: 我提到了这个这个 ,以及这个在SO上,并提出了重量单位的枚举,如下:

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

The problem is, when ever I try to deserialize above mentioned JSON I get this error saying: "Unrecognized field "LBS" (Class abcdWeight), not marked as ignorable" Exception stacktrace is like so: 问题是,当我尝试反序列化上面提到的JSON时,我得到这个错误说:“无法识别的字段”LBS“(类abcdWeight),没有标记为可忽略”异常堆栈跟踪是这样的:

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)

... ...

My questions are: Is the serialized JSON string for enum seem correct ? 我的问题是:枚举的序列化JSON字符串是否正确? What else should I include (or annotate) for the enum to be properly deserialized ? 我还应该包括(或注释)枚举是否正确反序列化?

I am assuming that in the public enum Unit code block, you mean Unit instead of WeightMeasurementUnit . 我假设在public enum Unit代码块中,你的意思是Unit而不是WeightMeasurementUnit

The Weight class has only a weight and a unit , so if you pass {"wt":100.5,"unit":"lbs"} , it should work, because a unit is just a unit without value. Weight类只有一个weight和一个unit ,所以如果你传递{"wt":100.5,"unit":"lbs"} ,它应该有效,因为一个unit只是一个没有价值的单位。 So there is no way for the deserializer to parse {"LBS":3} as a Unit . 因此,解串器无法将{"LBS":3}解析为一个Unit What is the 3 for? 什么是3

Another problem is that your value is "lbs" whereas you are passing "LBS". 另一个问题是你的值是“lbs”,而你传递的是“LBS”。 So either you need to standardise or you need to use unit.getValue().equalsIgnoreCase(val) 所以要么你需要标准化,要么你需要使用unit.getValue().equalsIgnoreCase(val)

I would suggest you update your jackson version to 2.7.0-rc2 (and probably also before) and then configure the ObjectMapper as follows: 我建议你将你的jackson版本更新到2.7.0-rc2(也可能在之前),然后按如下方式配置ObjectMapper:

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

In your enum you just have to override the toString() method: 在你的枚举中你只需要覆盖toString()方法:

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

You don't need any annotations or custom deserializers. 您不需要任何注释或自定义反序列化器。 This would be the way to map a simple enum to a json and vice-versa. 这将是将简单枚举映射到json的方法,反之亦然。

If your enum should be mapped from a special string you have to add a value field and a Constructor which assigns this field and return the value in the toString method. 如果你的枚举应该从一个特殊的字符串映射,你必须添加一个值字段和一个构造函数,它分配这个字段并返回toString方法中的值。

public enum Unit {
    KG("kilogram"),
    GM("gram"),
    LBS("blah"),
    OZ("anything");

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

    @Override
    public String toString() {
        return value;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM