Конвертировать JSONArray в Map с помощью Jackson - PullRequest
0 голосов
/ 07 апреля 2020

В нашем устаревшем коде мы отправляем тело запроса в форме HashMap, что я не могу изменить, поскольку это может повлиять на другие приложения.

Пример значения Hashmap = {name=name1, age=age1}

Однако у меня есть проблема с использованием HashMap, если в моем запросе несколько объектов JSON, например

HashMap<String, Object> map = new HashMap<String, Object>();

for (Person person: Persons) {
    map.put("name", "name1");
    map.put("age", "age1");
}

Если есть 2 или более людей, только имя и возраст последнего лица будут поставить в Map, потому что имя и возраст первого лица переопределены, потому что они имеют одинаковый ключ («имя» и «возраст»).

Мое желаемое значение карты было [{name=name1, age=age1}, {name=name2, age=age2}], но я только получил {name=name2, age=age2}

То, что я сделал, в каждом l oop я положил в JSONArray:

JSONArray jsonArray = new jsonArray();

for (Person person: Persons) {
    HashMap<String, Object> map = new HashMap<String, Object>();
    map.put("name", "name1");
    map.put("age", "age1");
    jsonArray.put(map);
}

Так что, когда я печатаю JSONArray, это :

[{"name":"name1", "age":"age1"}, {"name":"name2", "age":"age2"}]

Но, опять же, мне нужно преобразовать это в HashMap, чтобы я мог передать его в качестве параметра методу oursendRequest().

Я пытался использовать ObjectMapper в Джексон, но это не сработало.

Возможно ли это и как?

1 Ответ

1 голос
/ 07 апреля 2020

Я бы сначала десериализовал JSON в List людей. После этого я бы сгруппировал их по имени.

Main. java

package q61078696;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        try {
            List<Person> people = loadJSON("q61078696/people.json", Person.class);
            Map<String, List<Person>> groupedByName = people.stream()
                .collect(Collectors.groupingBy(Person::getName));
            System.out.println(groupedByName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String loadJSON(String resourceName) {
        InputStream is = Main.class.getClassLoader().getResourceAsStream(resourceName);
        String jsonString = null;
        try (Scanner scanner = new Scanner(is, StandardCharsets.UTF_8.name())) {
            jsonString = scanner.useDelimiter("\\A").next();
        }
        return jsonString;
    }

    public static <E> List<E> loadJSON(String resourceName, Class<E> clazz) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        String jsonString = loadJSON(resourceName);
        CollectionType typeReference = TypeFactory.defaultInstance().constructCollectionType(List.class, clazz);
        return mapper.readValue(jsonString, typeReference);
    }
}

Выход

{Tom=[{ "name": "Tom", "age": 28 }], Bob=[{ "name": "Bob", "age": 42 }, { "name": "Bob", "age": 21 }], Mary=[{ "name": "Mary", "age": 35 }]}

Person. java

package q61078696;

public class Person {
    private String name;
    private int age;

    public Person() {
        this(null, 0);
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return String.format("{ \"name\": \"%s\", \"age\": %d }", this.name, this.age);
    }
}

чел. json

[
  { "name" : "Bob",  "age" : 42 },
  { "name" : "Bob",  "age" : 21 },
  { "name" : "Mary", "age" : 35 },
  { "name" : "Tom",  "age" : 28 }
]

Зависимости

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.8</version>
</dependency>

Дополнительная информация

Если вы хотите отобразить по имени и избежать группировки (игнорируя дублирования) .

Это выдаст IllegalStateException, потому что есть дубликаты ключей, чтобы избежать этого, вам нужно будет получить доступ к карте.

Map<String, Person> groupedByName = people.stream()
    .collect(Collectors.toMap(Person::getName, Function.identity()));

Вы можете избежать этого, указав mergeFunction

Map<String, Person> groupedByName = people.stream()
    .collect(Collectors.toMap(
        Person::getName,     // keyMapper
        Function.identity(), // valueMapper
        (o1, o2) -> o1,      // mergeFunction (keep the first occurrence)
        TreeMap::new)        // mapSupplier
    );

Вы также можете указать supplier в 4-м параметре. Я выбрал TreeMap, чтобы сохранить имена ключей в порядке.

См .: https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap - java .util.function.Function- java .util.function.Function- java .util.function.BinaryOperator-

...