在我们的旧代码中,我们以 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
来保持名称键的顺序。
关于java - 使用 Jackson 将 JSONArray 转换为 Map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61078696/