1. 引言

本文将探讨在Java中将Gson的JsonArray转换为HashMap的多种实现方式。通过学习本文,你将掌握遍历JsonArray、提取元素并存入HashMap的核心技术,并能根据实际场景选择最优方案。

2. 理解Gson JsonArrayHashMap结构

Gson的JsonArray是Gson库中用于表示JSON元素数组的组件,典型结构如下:

[
    {"name": "John Doe", "age": 35},
    {"name": "Mary Jenn", "age": 41}
]

HashMap是Java中存储键值对的集合,每个键必须唯一。当插入重复键时,新值会覆盖旧值。这种特性正好与JSON对象中的唯一标识字段(如"name")天然契合。

3. 迭代法实现

这种方法通过手动遍历JsonArray元素,逐个提取键值对存入HashMap

Map<String, Integer> convertUsingIterative (JsonArray jsonArray) {
    Map<String, Integer> hashMap = new HashMap<>();
    for (JsonElement element : jsonArray) {
        JsonObject jsonObject = element.getAsJsonObject();
        String type = jsonObject.get("name").getAsString();
        Integer amount = jsonObject.get("age").getAsInt();
        hashMap.put(type, amount);
    }
    return hashMap;
}

实现要点:

  1. 创建空HashMap存储结果
  2. 遍历JsonArray中的每个元素
  3. 将每个JsonElement转换为JsonObject以便提取字段
  4. 使用getAsString()getAsInt()方法获取值

⚠️ 注意:Gson中数值通常以包含Number实例的JsonPrimitive形式存在,需显式转换类型。

验证代码示例:

@BeforeEach
void setUp() {
    jsonArray = new JsonArray();

    JsonObject jsonObject1 = new JsonObject();
    jsonObject1.addProperty("name", "John Doe");
    jsonObject1.addProperty("age", 35);
    jsonArray.add(jsonObject1);

    JsonObject jsonObject2 = new JsonObject();
    jsonObject2.addProperty("name", "Mary Jenn");
    jsonObject2.addProperty("age", 41);
    jsonArray.add(jsonObject2);
}

@Test
void testIterativeConversion() {
    Map<String, Integer> hashMap = JSONArrayToHashMapConverter.convertUsingIterative(jsonArray);
    assertEquals(35, hashMap.get("John Doe"));
    assertEquals(41, hashMap.get("Mary Jenn"));
}

✅ 适用场景:需要对每个元素进行精细控制的复杂转换场景

4. 流式处理实现

利用Java 8的Streams API,可以更简洁地实现转换:

Map<String, Integer> convertUsingStreams (JsonArray jsonArray) {
    return StreamSupport.stream(jsonArray.spliterator(), false)
      .map(JsonElement::getAsJsonObject)
      .collect(Collectors.toMap(
        jsonObject -> jsonObject.get("name").getAsString(),
        jsonObject -> jsonObject.get("age").getAsInt()
    ));
}

核心步骤:

  1. 通过StreamSupport.stream()创建流
    • 参数:JsonArraySpliterator和并行处理标志(此处设为false)
  2. 使用map()JsonElement转为JsonObject
  3. 通过Collectors.toMap()直接收集为HashMap

验证代码:

@Test
void testStreamConversion() {
    Map<String, Integer> hashMap = JSONArrayToHashMapConverter.convertUsingStreams(jsonArray);
    assertEquals(35, hashMap.get("John Doe"));
    assertEquals(41, hashMap.get("Mary Jenn"));
}

✅ 优势:

  • 代码简洁,符合函数式编程风格
  • 处理大型JSON数据集时性能更优
  • 避免显式循环,减少样板代码

5. 使用*fromJson()*方法

最后一种方案利用Gson的内置方法,先转换为List再合并为HashMap

Map<String, Integer> convertUsingGson(JsonArray jsonArray) {
    Map<String, Integer> hashMap = new HashMap<>();
    Gson gson = new Gson();
    List<Map<String, Object>> list = gson.fromJson(jsonArray, List.class);
    for (Map<String, Object> map : list) {
        String type = (String) map.get("name");
        Integer amount = ((Double) map.get("age")).intValue(); // Gson默认将数字解析为Double
        hashMap.put(type, amount);
    }
    return hashMap;
}

关键点:

  1. 使用gson.fromJson()JsonArray转为List
  2. 遍历List提取键值对
  3. 注意类型转换:Gson默认将数字解析为Double,需手动转Integer

验证代码:

@Test
void testGsonConversion() {
    Map<String, Integer> hashMap = JSONArrayToHashMapConverter.convertUsingGson(jsonArray);
    assertEquals(35, hashMap.get("John Doe"));
    assertEquals(41, hashMap.get("Mary Jenn"));
}

⚠️ 踩坑提示:直接使用gson.fromJson()时,数值类型会被统一解析为Double,需要额外类型转换

6. 总结

本文对比了三种JsonArrayHashMap的实现方案:

方法 适用场景 优势 注意事项
迭代法 复杂数据转换 精细控制每个元素 代码较冗长
流式处理 大数据集处理 简洁高效 需熟悉Stream API
fromJson() 简单直接转换 利用Gson内置功能 需处理类型转换

选择建议:

  • 需要精细控制元素处理 → 迭代法
  • 处理大型JSON数据集 → 流式处理
  • 简单转换场景 → fromJson()方法

完整示例代码已托管至GitHub,欢迎参考实践。


原始标题:How to Convert Gson JsonArray to HashMap | Baeldung