1. 概述

JSON(JavaScript Object Notation)是一种轻量级、结构化的数据交换格式。现代软件广泛使用JSON进行数据交换、配置管理和API通信。在Java中处理JSON通常依赖org.jsonJacksonGson等库。虽然将JSON对象转换为JSON数组看似简单,但正确的实现方式取决于输入结构和期望的输出格式。

本文将通过代码示例和JUnit测试,演示如何使用不同库实现JSON对象到JSON数组的转换。

2. 使用场景与注意事项

在REST API交互、数据管道或配置文件处理的应用中,JSON对象转JSON数组是常见需求。当原本建模为键值对的数据需要序列化、迭代或重新格式化时(例如前端框架要求接收对象数组而非Map),这种转换就变得必要。

选择转换方法前,开发者需明确:

  • ✅ 是否只需要JSON对象中的值
  • ✅ 是否需要同时保留键和值作为独立实体
  • ⚠️ 转换后的JSON数组用途(展示/传输/后续处理),这直接影响库选择和转换策略

3. 转换实现方案

下面介绍三种将JSON对象转换为JSON数组的方法。每种方案都会先封装核心逻辑,再通过JUnit验证正确性。

3.1. 使用org.json库

org.json库简单易用,已集成到许多Java项目中。它为JSONObjectJSONArray提供了直观的API。我们实现两种常见场景:

场景1:仅提取值

JSONArray convertValuesToArray(JSONObject jsonObject) {
    return new JSONArray(jsonObject.toMap().values());
}

此方法提取values()集合并包装为JSONArray,生成仅包含值的数组。

验证测试:

@Test
void givenFlatJSONObject_whenConvertValues_thenJSONArrayOfValues() {
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("id", 1);
    jsonObject.put("name", "Alice");

    OrgJsonConverter converter = new OrgJsonConverter();
    JSONArray result = converter.convertValuesToArray(jsonObject);

    assertEquals(2, result.length());
    assertTrue(result.toList().contains("Alice"));
}

场景2:键值对转对象数组

JSONArray convertToEntryArray(JSONObject jsonObject) {
    JSONArray result = new JSONArray();
    for (String key : jsonObject.keySet()) {
        JSONObject entry = new JSONObject();
        entry.put("key", key);
        entry.put("value", jsonObject.get(key));
        result.put(entry);
    }
    return result;
}

遍历JSONObject的每个键,创建包含keyvalue字段的新对象。

验证测试:

@Test
void givenFlatJSONObject_whenConvertToEntryArray_thenJSONArrayOfObjects() {
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("language", "Java");
    jsonObject.put("framework", "Spring");

    OrgJsonConverter converter = new OrgJsonConverter();
    JSONArray result = converter.convertToEntryArray(jsonObject);

    assertEquals(2, result.length());
    assertEquals("language", result.getJSONObject(0).get("key"));
}

3.2. 使用Jackson自定义逻辑

Jackson是功能强大的JSON处理库。虽然主要使用树模型,但通过内部转换仍可处理JSONObject

ArrayNode convertToArray(JSONObject jsonObject) {
    ObjectMapper mapper = new ObjectMapper();
    JsonNode jsonNode = mapper.convertValue(jsonObject.toMap(), JsonNode.class);

    ArrayNode result = mapper.createArrayNode();
    jsonNode.fields().forEachRemaining(entry -> {
        ObjectNode obj = mapper.createObjectNode();
        obj.put("key", entry.getKey());
        obj.set("value", entry.getValue());
        result.add(obj);
    });

    return result;
}

先将JSONObject转为Map,再用Jackson的convertValue()处理为JsonNode,最终构建包含键值对象的ArrayNode

验证测试:

@Test
void givenJSONObject_whenConvertToArray_thenArrayNodeOfKeyValueObjects() {
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("country", "India");
    jsonObject.put("code", "IN");

    JacksonConverter converter = new JacksonConverter();
    ArrayNode result = converter.convertToArray(jsonObject);

    assertEquals(2, result.size());
    assertEquals("country", result.get(0).get("key").asText());
}

3.3. 使用Gson处理JSON对象

Gson虽不直接支持JSONObject,但可通过内部Map转换实现:

JsonArray convertToKeyValueArray(JSONObject jsonObject) {
    JsonArray result = new JsonArray();
    jsonObject.keySet().forEach(key -> {
        JsonObject entry = new JsonObject();
        entry.addProperty("key", key);
        entry.add("value", com.google.gson.JsonParser.parseString(jsonObject.get(key).toString()));
        result.add(entry);
    });
    return result;
}

遍历键集合,为每个键值对创建包含keyvalue字段的新对象。

验证测试:

@Test
void givenJSONObject_whenConvertToKeyValueArray_thenJsonArrayWithObjects() {
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("brand", "Tesla");
    jsonObject.put("year", 2024);

    GsonConverter converter = new GsonConverter();
    JsonArray result = converter.convertToKeyValueArray(jsonObject);

    assertEquals(2, result.size());
    assertEquals("brand", result.get(0).getAsJsonObject().get("key").getAsString());
}

4. 总结

本文探讨了使用主流Java JSON库实现对象转数组的三种方案:

  • org.json:简洁直接,支持值提取和键值对转换
  • Jackson:适合复杂数据模型和Jackson生态集成
  • Gson:轻量级方案,适合Android或微服务环境

选择时需考虑:

  1. 项目现有技术栈
  2. 转换数据的复杂度
  3. 性能要求(Jackson通常性能最优)

⚠️ 踩坑提示:处理嵌套对象时需递归转换,以上示例仅展示扁平结构。完整代码见GitHub仓库