JSON 是現代 Web 交互的標準格式。Java 生態中有三大主流解析庫:org.json (輕量、JDK 內置風格)、Gson (Google、對象綁定強)、Jackson (Spring Boot 默認、性能最優、功能最全)。本文通過實戰代碼對比三者核心用法,助你選型與避坑。
| 概念 | org.json | Gson | Jackson |
|---|---|---|---|
| JSONObject | org.json.JSONObject | com.google.gson.JsonObject | com.fasterxml.jackson.databind.JsonNode (ObjectNode) |
| JSONArray | org.json.JSONArray | com.google.gson.JsonArray | com.fasterxml.jackson.databind.JsonNode (ArrayNode) |
| 對象綁定 | 手動 get/set | gson.fromJson(json, User.class) | mapper.readValue(json, User.class) |
| 流式解析 | 不支持 | JsonReader/JsonWriter | JsonParser/JsonGenerator (核心優勢) |
| Maven 坐標 | org.json:json:20231013 | com.google.code.gson:gson:2.10.1 | com.fasterxml.jackson.core:jackson-databind:2.15.2 |
// 依賴: org.json:json
String jsonStr = "{\"id\":1,\"name\":\"Tom\",\"age\":25,\"skills\":[\"Java\",\"Go\"]}";
public User parseWithOrgJson(String jsonStr) {
try {
JSONObject json = new JSONObject(jsonStr);
User user = new User();
user.setId(json.getLong("id"));
user.setName(json.getString("name"));
user.setAge(json.getInt("age"));
// 解析數組
JSONArray skillArr = json.getJSONArray("skills");
List skills = new ArrayList<>();
for (int i = 0; i < skillArr.length(); i++) {
skills.add(skillArr.getString(i));
}
user.setSkills(skills);
return user;
} catch (JSONException e) {
throw new RuntimeException("JSON 解析失敗", e);
}
}
// 依賴: com.google.code.gson:gson Gson gson = new Gson(); // 線程安全,可復用單例 // 字符串 -> 對象 User user = gson.fromJson(jsonStr, User.class); // 字符串 -> ListType listType = new TypeToken >(){}.getType(); List
users = gson.fromJson("[{\"id\":1},{\"id\":2}]", listType); // 處理字段名不一致 (@SerializedName) class User { @SerializedName("user_name") // JSON 字段 user_name -> Java 字段 name private String name; }
// 依賴: com.fasterxml.jackson.core:jackson-databind
ObjectMapper mapper = new ObjectMapper(); // 線程安全,全局單例
// 核心配置 (推薦全局配置一次)
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 忽略多餘字段
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // 日期輸出 ISO-8601
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
mapper.registerModule(new JavaTimeModule()); // 支持 LocalDateTime 等 Java 8 時間類型
// 字符串 -> 對象
User user = mapper.readValue(jsonStr, User.class);
// 字符串 -> List
List users = mapper.readValue(jsonArrayStr, new TypeReference>() {});
// 處理字段名映射 (@JsonProperty)
class User {
@JsonProperty("user_name")
private String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
}
User user = new User(1L, "Tom", 25, Arrays.asList("Java", "Go"));
// org.json
JSONObject json = new JSONObject();
json.put("id", user.getId());
json.put("name", user.getName());
// ... 手動構建,繁瑣
// Gson
String jsonGson = gson.toJson(user); // {"id":1,"name":"Tom","age":25,"skills":["Java","Go"]}
// Jackson
String jsonJackson = mapper.writeValueAsString(user);
// 格式化輸出
String pretty = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
// Jackson JsonNode 樹模型 (靈活、高性能)
JsonNode root = mapper.readTree(jsonStr);
Long id = root.path("id").asLong(); // path 安全獲取,無則返回 MissingNode
String name = root.path("name").asText();
JsonNode skillsNode = root.path("skills");
if (skillsNode.isArray()) {
for (JsonNode skill : skillsNode) {
System.out.println(skill.asText());
}
}
// Gson JsonParser
JsonElement element = JsonParser.parseString(jsonStr);
JsonObject obj = element.getAsJsonObject();
JsonArray skills = obj.getAsJsonArray("skills");
// Jackson (推薦 Java 8+ LocalDateTime)
mapper.registerModule(new JavaTimeModule()); // 必須註冊
// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") 標註字段
// Gson
Gson gson = new GsonBuilder()
.registerTypeAdapter(LocalDateTime.class, new JsonSerializer() {
@Override public JsonElement serialize(LocalDateTime src, Type type, JsonSerializationContext context) {
return new JsonPrimitive(src.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
})
.create();
// Gson: 默認不輸出 null 字段 // 輸出 null: new GsonBuilder().serializeNulls().create() // Jackson: 默認輸出 null // 忽略 null: mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) // 或類上: @JsonInclude(JsonInclude.Include.NON_NULL)
// Jackson 流式 API (核心優勢:低內存、高性能)
try (JsonParser parser = mapper.getFactory().createParser(new File("huge.json"))) {
while (parser.nextToken() != JsonToken.END_OBJECT) {
if (parser.currentToken() == JsonToken.FIELD_NAME && "id".equals(parser.currentName())) {
parser.nextToken(); // 移動到 VALUE
long id = parser.getLongValue();
// 處理 id...
}
}
}
// Gson 流式
try (JsonReader reader = new JsonReader(new FileReader("huge.json"))) {
reader.beginObject();
while (reader.hasNext()) { ... }
}
| 場景 | 推薦庫 | 理由 |
|---|---|---|
| Spring Boot / 微服務 / 高性能 / 複雜映射 | Jackson | 生態完善、流式解析、模塊化擴展、Spring 生態原生 |
| Android / 簡單對象綁定 / 無 Spring 環境 | Gson | API 極簡、體積較小、適應性強 |
| 極簡依賴 / 無實體類動態解析 / 單文件工具類 | org.json | 單 jar 無依賴、API 直觀、Android 內置 (org.json 包) |
| 大數據/日誌/流式處理 | Jackson Streaming API | 唯一成熟的流式解析器,內存常數級 |
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)。JSON 解析在 Java 中已是基建級能力。**Jackson 是企業級首選**,Gson 適合輕量客戶端,org.json 適合極簡場景。掌握 對象綁定 (一行代碼)、樹模型動態解析 (JsonNode)、流式解析 (大文件)、日期/Null/命名策略配置 五大核心技能,即可應對 99% 業務場景。建議項目統一封裝 JsonUtils 工具類,內部委託 Jackson,對外暴露簡潔 API,屏蔽底層庫細節,便於未來升級遷移。