我有一个接口Event
和多个实现此接口的枚举(UserEvent
,BusinessEvent
等)。
我想反序列化以下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
属性,但在这种情况下,只有一个字符串直接映射到枚举值。
答案 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));
}
}