java - 使用 Jackson 将 JSONArray 转换为 Map

标签 java json jackson hashmap

在我们的旧代码中,我们以 HashMap 的形式发送请求正文,这是我无法更改的,因为其他应用程序可能会受到影响。

示例 HashMap 值 = {name=name1,age=age1}

但是,例如,如果我的请求中有多个 JSON 对象,我在使用 HashMap 时会遇到问题

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

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

如果有 2 个人或更多人,则只有最后一个人的姓名和年龄会被放入 Map 中,因为第一个人的姓名和年龄会被覆盖,因为他们具有相同的键(“name ”和“年龄”)。

我想要的 map 值是[{name=name1,age=age1},{name=name2,age=age2}],但我只得到{name=name2,age =年龄2}

我所做的是,在每个循环中,我将其放入 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() 方法。

我尝试在 Jackson 中使用 ObjectMapper,但没有成功。

这可能吗?如何实现?

最佳答案

我首先会将 JSON 反序列化为人员列表。之后,我会按名称对它们进行分组。

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);
    }
}

people.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 。

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
    );

您还可以在第四个参数中指定供应商。我选择了 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-

关于java - 使用 Jackson 将 JSONArray 转换为 Map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61078696/

相关文章:

java - 数组中的两个数字

java 日志记录/日志服务器

javascript - 安全地将 JSON 字符串转换为对象

Java - 遍历数组节点

java - 将集合反序列化为外部数组

java - 需要 boolean 值,找到 int?

java - 从 ArrayList 中删除重复项的算法

python - 使用 python 3 将 CSV 转换为 JSON

java - jackson writeValueAsString : valid JSON not valid anymore

java - 如果字段不存在, jackson 反序列化失败