Десериализовать дубликаты ключей в список с помощью Джексона - PullRequest
3 голосов
/ 30 апреля 2020

Я пытаюсь десериализовать json в объект. Тем не менее, json имеет дубликаты ключей. Я не могу изменить json, и я хотел бы использовать Джексона, чтобы изменить дубликаты ключей в список.

Вот пример полученного json:

{
  "myObject": {
    "foo": "bar1",
    "foo": "bar2"
  }
}

И вот что я хотел бы после десериализации:

{
  "myObject": {
    "foo": ["bar1","bar2"]
  }
}

Я создал свой класс примерно так:

public class MyObject {
    private List<String> foo;
    // constructor, getter and setter
}

Я пытался использовать DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY из objectMapper, но все, что он делает, это взяв последний ключ и добавив его в список следующим образом:

{
  "myObject": {
    "foo": ["bar2"]
  }
}

Вот моя objectMapper конфигурация:

new ObjectMapper().configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

Есть ли способ десериализации дубликатов ключей в списке используя Джексона?

Ответы [ 2 ]

4 голосов
/ 01 мая 2020

Вам необходимо использовать com.fasterxml.jackson.annotation.JsonAnySetter аннотацию:

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
}

На стороне Java у вас есть список со значениями:

bar1
bar2
0 голосов
/ 01 мая 2020

Дополнение ответа от @ Michał Ziober : если вам нужно обработать случай смешивания отдельных значений и списков / карт:

{  
  "myObject": {
     "foo": "bar1",
     "foo": ["bar2", "bar3"],
     "foo": {"bar": "baz"}
  }
}

это можно сделать в том же 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()));  
    }
}

Тогда результат будет:

{
  "myObject" : {
    "foos" : [ "bar1", "bar2", "bar3", "bar:baz" ]
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...