How to enforce ACCEPT_SINGLE_VALUE_AS_ARRAY in jackson's deserialization process using annotation
You can use @JsonFormat annotation,
public class MyClass {
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
private List<String> value;
}
To work with this you need to have Jackson version min 2.7.0
. You can also use other available JsonFormat Features
For version 2.6.x
@Autowired private ObjectMapper mapper;
//...
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
- Add this code to your
Initializer Class
. - Or you can directly configure
Jackson
in yourBean Configuration
These would solve the issue but it will be activated for every deserialization
process.
I'm just answering my own question for clarity. One of the answers was to upgrade to the higher version so that I can use annotations. I cannot do it due to dependency restrictions of my project.
As a result, based on Michal Foksa answer I solved my problem by creating a custom deserializer. Its as below:
On my property:
@JsonDeserialize(using = CustomStringDeserializer.class)
private List<String> value;
And my Deserializer:
public class CustomStringDeserializer extends JsonDeserializer<List<String>>{
@Override
public List<String> deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature. ACCEPT_SINGLE_VALUE_AS_ARRAY);
return mapper.readValue(p, List.class);
}
}
I would create a custom JsonDeserializer
where I would deal with both cases and annotate value class property with the deserializer.
Deserializer:
public class StringListDeserializer extends JsonDeserializer<List<String>>{
@Override
public List<String> deserialize(JsonParser parser, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
List<String> ret = new ArrayList<>();
ObjectCodec codec = parser.getCodec();
TreeNode node = codec.readTree(parser);
if (node.isArray()){
for (JsonNode n : (ArrayNode)node){
ret.add(n.asText());
}
} else if (node.isValueNode()){
ret.add( ((JsonNode)node).asText() );
}
return ret;
}
}
MyClass:
public class MyClass {
.
@JsonDeserialize(using = StringListDeserializer.class)
private List<String> value;
.
}
Hope it helps.
BTW: If there is a way how to deal with such a case with just an annotation, I also want to know it.