简体   繁体   English

如何反序列化json以在java中使用jackson进行枚举?

[英]How to deserialize json to enum with jackson in java?

I have an interface with name Field as below:我有一个名为 Field 的接口,如下所示:

public interface Field {
}

This interface is in the module A .该接口位于模块A 中 I have an enum called BField which is in module B and is implemented as below:我有一个名为 BField 的枚举,它在模块B 中,实现如下:

public enum BField implements Field {
    SOME_FIELD
}

There is a class named C in the module A as below:模块A 中有一个名为 C 的类,如下所示:

public class C implements Serializable {
    private Set<Field> f;

    public Set<Field> getF() { return f; }
    public void setF(Set<Field> f) { this f = f; }
}

I have a REST method as below:我有一个 REST 方法如下:

@RequestMapping(method=RequestMethod.Post, value="/save")
@ResponseBody
public void save (@RequestBody C c) {
    //save c
}

I send this JSON object to this method:我将此 JSON 对象发送到此方法:

{
    "f": ["SOME_FIELD"]
}

then I get HTTP 400 bad request error code with the following exception log:然后我收到带有以下异常日志的 HTTP 400 错误请求错误代码:

abstract types can only be instantiated with additional type information抽象类型只能用附加类型信息实例化

The hierarchy of the modules is module B is dependent to module A .模块的层次结构是模块B依赖于模块A I tried to use @JsonTypeInfo but the dependency between modules works as a limit and does not let me to use BField.class in the @JsonSubTypes annotation for the field f in class C.我尝试使用@JsonTypeInfo,但模块之间的依赖是一个限制,不允许我在类 C 中的字段 f 的 @JsonSubTypes 注释中使用 BField.class。

The problem here is not the enum , it's the Set and the Field interfaces.这里的问题不是enum ,而是SetField接口。

You need to tell Jackson what kind of Set and what kind of Field you want, and you can do that by annotating that property with:你需要告诉 Jackson 你想要什么样的Set和什么样的Field ,你可以通过注释该属性来做到这一点:

@JsonDeserialize(as = EnumSet.class, contentAs = BField.class)

At last I find the solution.最后我找到了解决方案。

  1. I remove <mvc:annotation-driven/> in my context我在上下文中删除了<mvc:annotation-driven/>
  2. Add @JsonDeserialize(as = EnumSet.class) annotation for field private Set<Field> f;为字段private Set<Field> f;添加@JsonDeserialize(as = EnumSet.class)注释private Set<Field> f; in class C.在 C 班。
  3. create a class called JsonBFieldDeserializer in module B as below:在模块B 中创建一个名为 JsonBFieldDeserializer 的类,如下所示:

     public class JsonBFieldDeserializer extends StdDeserializer<Field> { public JsonBFieldDeserializer() { this(null); } public JsonBFieldDeserializer(Class<?> vc) { super(vc); } @Overrid public Field deserialize(JsonParser jsonParser, DeserializationContext dC) throws IOException, JsonProcessingException { JsonNode node = jsonParser.getCodec().readTree(); String text = node.asText(); return BField.valueOf(text); } }
  4. Create a class called BConfiguration in module B as below:在模块B 中创建一个名为 BConfiguration 的类,如下所示:

     @Configuration public class BConfiguration extends WebMVCConfigurationSupport { protected void configureMessageConverters(List<HttpMessageConverters<?>> converters){ converters.add(convert()); addDefaultHttpMessageConverters(converters); } @Bean MappingJackson2HttpMessageConverter convert(){ MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(Field.class, new JsonBFieldDeserializer()); objectMapper.registerModule(module); converter.setObjectMapper(objectMapper); return converter; } }
  5. Be careful to use fasterxml jackson not codehaus library!小心使用fastxml jackson而不是codehaus 库!

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

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