Java JSON 處理

JSON (JavaScript Object Notation) 是常用的資料交換格式。Java 可以使用多種函式庫來處理 JSON。

常用 JSON 函式庫

  • Jackson:最流行,功能豐富
  • Gson:Google 開發,簡單易用
  • org.json:輕量級
  • JSON-B:Java EE 標準

Jackson

新增依賴

<!-- Maven -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

Java 物件轉 JSON

import com.fasterxml.jackson.databind.ObjectMapper;

// 定義類別
public class User {
    private String name;
    private int age;
    private String email;
    
    // 建構子、getter、setter
}

// 轉換
ObjectMapper mapper = new ObjectMapper();
User user = new User("Alice", 25, "alice@example.com");

// 轉為 JSON 字串
String json = mapper.writeValueAsString(user);
// {"name":"Alice","age":25,"email":"alice@example.com"}

// 轉為 JSON 字串(格式化)
String prettyJson = mapper.writerWithDefaultPrettyPrinter()
    .writeValueAsString(user);

// 寫入檔案
mapper.writeValue(new File("user.json"), user);

JSON 轉 Java 物件

String json = "{\"name\":\"Bob\",\"age\":30,\"email\":\"bob@example.com\"}";

// 轉為物件
User user = mapper.readValue(json, User.class);

// 從檔案讀取
User userFromFile = mapper.readValue(new File("user.json"), User.class);

// 從 URL 讀取
User userFromUrl = mapper.readValue(new URL("http://api.example.com/user"), User.class);

處理陣列和集合

// JSON 陣列
String jsonArray = "[{\"name\":\"Alice\"},{\"name\":\"Bob\"}]";

// 轉為 List
List<User> users = mapper.readValue(jsonArray, 
    new TypeReference<List<User>>() {});

// 轉為陣列
User[] userArray = mapper.readValue(jsonArray, User[].class);

// List 轉 JSON
String json = mapper.writeValueAsString(users);

處理 Map

String json = "{\"name\":\"Alice\",\"age\":25}";

// 轉為 Map
Map<String, Object> map = mapper.readValue(json, 
    new TypeReference<Map<String, Object>>() {});

// Map 轉 JSON
Map<String, Object> data = new HashMap<>();
data.put("name", "Bob");
data.put("age", 30);
String jsonFromMap = mapper.writeValueAsString(data);

Jackson 註解

public class User {
    @JsonProperty("user_name")  // JSON 欄位名稱
    private String name;
    
    @JsonIgnore  // 忽略此欄位
    private String password;
    
    @JsonInclude(JsonInclude.Include.NON_NULL)  // null 時不輸出
    private String email;
    
    @JsonFormat(pattern = "yyyy-MM-dd")  // 日期格式
    private LocalDate birthday;
}

Gson

新增依賴

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

基本使用

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

Gson gson = new Gson();

// Java 轉 JSON
User user = new User("Alice", 25);
String json = gson.toJson(user);

// JSON 轉 Java
User parsed = gson.fromJson(json, User.class);

// 格式化輸出
Gson prettyGson = new GsonBuilder().setPrettyPrinting().create();
String prettyJson = prettyGson.toJson(user);

處理集合

// List 轉 JSON
List<User> users = Arrays.asList(new User("Alice", 25), new User("Bob", 30));
String json = gson.toJson(users);

// JSON 轉 List
Type listType = new TypeToken<List<User>>() {}.getType();
List<User> parsed = gson.fromJson(json, listType);

Gson 設定

Gson gson = new GsonBuilder()
    .setPrettyPrinting()                    // 格式化
    .setDateFormat("yyyy-MM-dd")            // 日期格式
    .serializeNulls()                       // 包含 null 欄位
    .excludeFieldsWithoutExposeAnnotation() // 只序列化 @Expose 欄位
    .create();

實際應用

API 回應處理

public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;
    // getter, setter
}

// 解析 API 回應
String response = // 從 API 取得
ObjectMapper mapper = new ObjectMapper();
ApiResponse<User> apiResponse = mapper.readValue(response,
    new TypeReference<ApiResponse<User>>() {});

if (apiResponse.getCode() == 200) {
    User user = apiResponse.getData();
}

設定檔讀取

// config.json
// {"server": {"host": "localhost", "port": 8080}}

public class Config {
    private Server server;
}

public class Server {
    private String host;
    private int port;
}

// 讀取
Config config = mapper.readValue(new File("config.json"), Config.class);

動態 JSON 處理

// 使用 JsonNode(Jackson)
String json = "{\"name\":\"Alice\",\"scores\":[85,90,95]}";
JsonNode node = mapper.readTree(json);

String name = node.get("name").asText();
JsonNode scores = node.get("scores");
for (JsonNode score : scores) {
    System.out.println(score.asInt());
}

效能比較

函式庫序列化速度反序列化速度記憶體使用
Jackson
Gson
org.json

一般建議使用 Jackson,它的功能最完整且效能最好。