问题
I'm trying to deserialize json into object. However, the json has duplicate keys. I cannot change the json and I would like to use Jackson to change duplicate keys to a list.
Here is an example of the json I retrieve:
{
"myObject": {
"foo": "bar1",
"foo": "bar2"
}
}
And here is what I would like after deserialization:
{
"myObject": {
"foo": ["bar1","bar2"]
}
}
I created my class like so:
public class MyObject {
private List<String> foo;
// constructor, getter and setter
}
I tried to use DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY
from objectMapper
but all it does is taking the last key and add it to the list like this:
{
"myObject": {
"foo": ["bar2"]
}
}
Here is my objectMapper
configuration:
new ObjectMapper().configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
Is there a way to deserialize duplicate keys to a list using Jackson?
回答1:
You need to use com.fasterxml.jackson.annotation.JsonAnySetter
annotation:
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class JsonPathApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
Root root = mapper.readValue(jsonFile, Root.class);
root.getMyObject().getFoos().forEach(System.out::println);
}
}
class Root {
private MyObject myObject;
// getters, setters, toString
}
class MyObject {
private List<String> foos = new ArrayList<>();
@JsonAnySetter
public void manyFoos(String key, String value) {
foos.add(value);
}
// getters, setters, toString
}
On Java
side you have a list with values:
bar1
bar2
回答2:
Supplementing answer from @Michał Ziober: if you need to handle case of mixing single values and lists/maps:
{
"myObject": {
"foo": "bar1",
"foo": ["bar2", "bar3"],
"foo": {"bar": "baz"}
}
}
this can be done in the same manyFoos
:
@SuppressWarnings("unchecked")
@JsonAnySetter
public void manyFoos(String key, Object value) {
System.out.println("key = " + key + " -> " + value.getClass() + ": " + value);
if (value instanceof String)
foos.add((String)value);
else if (value instanceof Collection<?>) {
foos.addAll((Collection<? extends String>)value);
}
else if (value instanceof Map<?, ?>) {
Map<? extends String, ? extends String> subFoo = (Map<? extends String, ? extends String>) value;
subFoo.entrySet().forEach(e -> foos.add(e.getKey() + ":" + e.getValue()));
}
}
Then the result will be:
{
"myObject" : {
"foos" : [ "bar1", "bar2", "bar3", "bar:baz" ]
}
}
来源:https://stackoverflow.com/questions/61528937/deserialize-duplicate-keys-to-list-using-jackson