Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何用java中的jackson将json反序列化为enum?_Java_Json_Jackson - Fatal编程技术网

如何用java中的jackson将json反序列化为enum?

如何用java中的jackson将json反序列化为enum?,java,json,jackson,Java,Json,Jackson,我有一个与名称字段的接口,如下所示: public interface Field { } public enum BField implements Field { SOME_FIELD } public class C implements Serializable { private Set<Field> f; public Set<Field> getF() { return f; } public void setF(Set

我有一个与名称字段的接口,如下所示:

public interface Field {
}
public enum BField implements Field {
    SOME_FIELD
}
public class C implements Serializable {
    private Set<Field> f;

    public Set<Field> getF() { return f; }
    public void setF(Set<Field> f) { this f = f; }
}
@RequestMapping(method=RequestMethod.Post, value="/save")
@ResponseBody
public void save (@RequestBody C c) {
    //save c
}
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);
    }
}
@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;
    }
}
此接口位于模块A中。 我有一个名为BField的枚举,它位于模块B中,实现如下:

public interface Field {
}
public enum BField implements Field {
    SOME_FIELD
}
public class C implements Serializable {
    private Set<Field> f;

    public Set<Field> getF() { return f; }
    public void setF(Set<Field> f) { this f = f; }
}
@RequestMapping(method=RequestMethod.Post, value="/save")
@ResponseBody
public void save (@RequestBody C c) {
    //save c
}
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);
    }
}
@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;
    }
}
模块a中有一个名为C的类,如下所示:

public interface Field {
}
public enum BField implements Field {
    SOME_FIELD
}
public class C implements Serializable {
    private Set<Field> f;

    public Set<Field> getF() { return f; }
    public void setF(Set<Field> f) { this f = f; }
}
@RequestMapping(method=RequestMethod.Post, value="/save")
@ResponseBody
public void save (@RequestBody C c) {
    //save c
}
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);
    }
}
@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;
    }
}
我将此JSON对象发送到此方法:

{
    "f": ["SOME_FIELD"]
}
然后,我得到HTTP 400错误请求错误代码和以下异常日志:

抽象类型只能用其他类型实例化 信息


模块的层次结构为模块B依赖于模块A。我试图使用@JsonTypeInfo,但模块之间的依赖关系是一个限制,不允许我在@JsonSubTypes注释中为类C中的字段f使用BField.class。

这里的问题不是
枚举
,而是
集合
字段
接口

您需要告诉Jackson您想要什么类型的
集合
和什么类型的
字段
,您可以通过以下方式注释该属性:

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

最后我找到了解决办法

  • 我在上下文中删除
  • 为字段
    私有集f添加
    @JsonDeserialize(as=EnumSet.class)
    注释在C类中
  • 在模块B中创建一个名为JsonBFieldDeserializer的类,如下所示:

    public interface Field {
    }
    
    public enum BField implements Field {
        SOME_FIELD
    }
    
    public class C implements Serializable {
        private Set<Field> f;
    
        public Set<Field> getF() { return f; }
        public void setF(Set<Field> f) { this f = f; }
    }
    
    @RequestMapping(method=RequestMethod.Post, value="/save")
    @ResponseBody
    public void save (@RequestBody C c) {
        //save c
    }
    
    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);
        }
    }
    
    @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;
        }
    }
    
    公共类JsonBFieldDeserializer扩展了StdDeserializer{
    公共JsonBFieldDeserializer(){
    这个(空);
    }
    公共JsonBFieldDeserializer(类vc){
    超级(vc);
    }
    @凌驾
    公共字段反序列化(JsonParser、JsonParser、反序列化上下文dC)引发IOException、JsonProcessingException{
    JsonNode节点=jsonParser.getCodec().readTree();
    String text=node.asText();
    返回BField.valueOf(文本);
    }
    }
    
  • 在模块B中创建一个名为BConfiguration的类,如下所示:

    public interface Field {
    }
    
    public enum BField implements Field {
        SOME_FIELD
    }
    
    public class C implements Serializable {
        private Set<Field> f;
    
        public Set<Field> getF() { return f; }
        public void setF(Set<Field> f) { this f = f; }
    }
    
    @RequestMapping(method=RequestMethod.Post, value="/save")
    @ResponseBody
    public void save (@RequestBody C c) {
        //save c
    }
    
    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);
        }
    }
    
    @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;
        }
    }
    
    @配置
    公共类B配置扩展了WebMVCConfigurationSupport{
    
    受保护的无效配置MessageConverters(ListXcuse我忘了注意接口字段有多个实现。例如模块B中的BField和模块D中的DField。谢谢。当我只使用接口字段的一个实现来测试它时,您的解决方案是有效的,但我也必须依赖模块A到模块B。我的问题有点不同。首先,我不想依赖模块A到模块B,第二个接口字段在多个模块中有多个实现。只有从模块中收集Jackson片段并将其聚合,您才可能需要它;一个示例是Druid如何允许您注册自定义解析器和其他内容: