简体   繁体   English

Jackson - 将接口反序列化为枚举

[英]Jackson - Deserialize Interface to enum

I have an interface Event and multiple enums that implement this interface ( UserEvent , BusinessEvent , etc).我有一个接口Event和多个实现这个接口的枚举( UserEventBusinessEvent等)。

I want to deserialize the following json data:我想反序列化以下 json 数据:

{
  "event" : "SIGNUP"
}

To this bean:给这个豆子:

public class Input
{ 
   private Event event;

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

public enum UserEvent implements Event
{
    SIGNUP;
}

Here, i'd like event to be deserialized to UserEvent.SIGNUP .在这里,我希望将事件反序列化为UserEvent.SIGNUP

How can I accomplish this?我怎样才能做到这一点? Reading up on @JsonTypeInfo seems to indicate that an additional type attribute would be needed, but in this case, there's just one string which maps directly to an enum value.阅读@JsonTypeInfo似乎表明需要一个额外的type属性,但在这种情况下,只有一个字符串直接映射到枚举值。

You are using Event interface for field event in Input and jackson doesn't know anything about UserEvent as implementation of this interface.您正在将Event接口用于Input字段event ,而 jackson 对UserEvent作为此接口的实现一无所知。

You can use custom JsonDeserializer to get value:您可以使用自定义JsonDeserializer来获取价值:

public interface Event {
}

public static class Input
{
    private Event event;

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

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

public enum UserEvent implements Event
{
    SIGNUP;
}

public static class EventDeserializer  extends StdDeserializer<Event> {

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

For a single enum the jsonschema2pojo-maven-plugin generates code like the following:对于单个枚举,jsonschema2pojo-maven-plugin 生成如下代码:

@JsonCreator
public static Foo fromValue(String value) {
    Foo constant = CONSTANTS.get(value);
    if (constant == null) {
        throw new IllegalArgumentException(value);
    } else {
        return constant;
    }
}

I guess you could write a factory method which is annotated with @JsonCreator and somehow decides which enum to choose.我想您可以编写一个用@JsonCreator 注释的工厂方法,并以某种方式决定选择哪个枚举。 I'm not sure if it matters much where you put this method.我不确定你把这个方法放在哪里很重要。

Having a similar task I ended up creating a custom deserializer:有一个类似的任务,我最终创建了一个自定义反序列化器:

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

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

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