Reputation: 597
I have an interface with name Field as below:
public interface Field {
}
This interface is in the module A. I have an enum called BField which is in module B and is implemented as below:
public enum BField implements Field {
SOME_FIELD
}
There is a class named C in the module A as below:
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:
@RequestMapping(method=RequestMethod.Post, value="/save")
@ResponseBody
public void save (@RequestBody C c) {
//save c
}
I send this JSON object to this method:
{
"f": ["SOME_FIELD"]
}
then I get HTTP 400 bad request error code with the following exception log:
abstract types can only be instantiated with additional type information
The hierarchy of the modules is module B is dependent to module 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.
Upvotes: 1
Views: 1459
Reputation: 597
At last I find the solution.
<mvc:annotation-driven/>
in my context@JsonDeserialize(as = EnumSet.class)
annotation for field private Set<Field> f;
in class C.create a class called JsonBFieldDeserializer in module B as below:
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);
}
}
Create a class called BConfiguration in module B as below:
@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;
}
}
Be careful to use fasterxml jackson not codehaus library!
Upvotes: 0
Reputation: 38255
The problem here is not the enum
, it's the Set
and the Field
interfaces.
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:
@JsonDeserialize(as = EnumSet.class, contentAs = BField.class)
Upvotes: 1