杰克逊 - 将接口反序列化为枚举

时间:2017-01-20 14:13:13

标签: java json jackson

我有一个接口Event和多个实现此接口的枚举(UserEventBusinessEvent等)。

我想反序列化以下json数据:

{
  "event" : "SIGNUP"
}

对这个bean:

public class Input
{ 
   private Event event;

   public Event getEvent() {..}
   public void setEvent(Event event) {..}
}

public enum UserEvent implements Event
{
    SIGNUP;
}

在这里,我希望将事件反序列化为UserEvent.SIGNUP

我怎样才能做到这一点?阅读@JsonTypeInfo似乎表明需要额外的type属性,但在这种情况下,只有一个字符串直接映射到枚举值。

3 个答案:

答案 0 :(得分:2)

对于单个枚举,jsonschema2pojo-maven-plugin生成如下代码:

export class Product  {
    constructor(
      public id: number,
      public name: string,
      public description: string,
      public image: string,
      public price: number,
      public type: ProductType
    ) { }
}

我猜你可以写一个用@JsonCreator注释的工厂方法,并以某种方式决定选择哪个枚举。我不确定这个方法的重要性。

答案 1 :(得分:2)

您在Event中使用event接口查看字段Input,杰克逊对UserEvent的任何信息都不了解此接口的实现。

您可以使用自定义JsonDeserializer获取值:

public interface Event {
}

public static class Input
{
    private Event event;

    @JsonDeserialize(using = UserEventDeserializer.class)
    public Event getEvent() {
        return event;
    }

    public void setEvent(Event event) {
        this.event = event;
    }
}

public enum UserEvent implements Event
{
    SIGNUP;
}

public static class UserEventDeserializer  extends StdDeserializer<Event> {

    protected UserEventDeserializer() {
        super(Event.class);
    }

    @Override
    public Event deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        return UserEvent.valueOf(p.getText());
    }
}

@Test
public void converEnum() throws Exception {
    ObjectMapper objectMapper = new ObjectMapper();
    Input input = objectMapper.readValue("{\n" +
            "  \"event\" : \"SIGNUP\"\n" +
            "}", Input.class);

    Assert.assertThat(input.getEvent(), Matchers.is(UserEvent.SIGNUP));
}

答案 2 :(得分:0)

完成类似的任务,我最终创建了一个自定义反序列化器:

public class IFooDeserializer extends StdDeserializer<IFoo> {

    public IFooDeserializer() {
        this(null);
    }

    public IFooDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public IFoo deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String value = p.getCodec().readValue(p, String.class);
        return Stream.of(GoodFoo.values(), BadFoo.values())
                .flatMap(Stream::of)
                .filter(el -> el.name().equals(value))
                .findAny()
                .orElseThrow(() -> new RuntimeException("Could not deserialize foo: " + value));
    }
}