XML 解析繁瑣、HTML 片段耦合度高,JSON 以輕量、原生 JavaScript 支持、跨語言通用成為 Ajax 數據交換首選。本文系統講解 JSON 格式規範、JavaScript 原生處理、jQuery/Prototype 封裝調用、Java 服務端編碼輸出全流程,附完整代碼示例。
| 類型 | JSON 表示 | 示例 |
|---|---|---|
| String | 雙引號包裹,特殊字符轉義 | "Hello\nWorld" |
| Number | 整數/浮點數/科學計數法 | 123 -3.9e10 |
| Boolean | true / false(無引號) | true |
| Null | null(無引號) | null |
| Array | 方括號,逗號分隔 | ["abc", 123, false, null] |
| Object | 大括號,鍵值對,鍵必須雙引號 | {"city":"Beijing","postcode":100025} |
嵌套示例:
{
"name": "Michael",
"address": {
"city": "Beijing",
"street": "Chaoyang Road",
"postcode": 100025
}
}
// 發送請求
fetch('/api/user/1')
.then(res => res.json()) // 自動解析 JSON
.then(data => {
console.log(data.name); // "Michael"
console.log(data.address.city); // "Beijing"
updateUI(data);
})
.catch(err => console.error(err));
// 或使用 async/await
async function loadUser() {
const res = await fetch('/api/user/1');
const data = await res.json();
return data;
}
$.ajax({
url: '/api/user/1',
dataType: 'json', // 關鍵:自動調用 JSON.parse
success: function(data) {
console.log(data.name);
$('#user-name').text(data.name);
},
error: function(xhr, status, err) {
console.error('載入失敗:', err);
}
});
// 簡化 GET
$.getJSON('/api/user/1', function(data) {
console.log(data.address.street);
});
new Ajax.Request('/api/user/1', {
method: 'get',
onSuccess: function(transport) {
var json = transport.responseText.evalJSON(); // Prototype 擴展
// 處理 json...
}
});
為理解本質,展示無第三方庫的手工編碼(生產建議用 Jackson/Gson)。
public class JsonUtil {
public static String toJson(Object o) {
if (o == null) return "null";
if (o instanceof String) return string2Json((String) o);
if (o instanceof Boolean) return boolean2Json((Boolean) o);
if (o instanceof Number) return number2Json((Number) o);
if (o instanceof Map) return map2Json((Map<String, Object>) o);
if (o instanceof Object[]) return array2Json((Object[]) o);
throw new RuntimeException("Unsupported type: " + o.getClass().getName());
}
private static String string2Json(String s) {
StringBuilder sb = new StringBuilder(s.length() + 20);
sb.append('"');
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '"': sb.append("\\\""); break;
case '\\': sb.append("\\\\"); break;
case '/': sb.append("\\/"); break;
case '\b': sb.append("\\b"); break;
case '\f': sb.append("\\f"); break;
case '\n': sb.append("\\n"); break;
case '\r': sb.append("\\r"); break;
case '\t': sb.append("\\t"); break;
default: sb.append(c);
}
}
sb.append('"');
return sb.toString();
}
private static String number2Json(Number n) { return n.toString(); }
private static String boolean2Json(Boolean b) { return b.toString(); }
private static String array2Json(Object[] arr) {
if (arr.length == 0) return "[]";
StringBuilder sb = new StringBuilder(arr.length << 4);
sb.append('[');
for (Object o : arr) {
sb.append(toJson(o)).append(',');
}
sb.setCharAt(sb.length() - 1, ']');
return sb.toString();
}
private static String map2Json(Map<String, Object> map) {
if (map.isEmpty()) return "{}";
StringBuilder sb = new StringBuilder(map.size() << 4);
sb.append('{');
for (Map.Entry<String, Object> e : map.entrySet()) {
sb.append('"').append(e.getKey()).append('"').append(':')
.append(toJson(e.getValue())).append(',');
}
sb.setCharAt(sb.length() - 1, '}');
return sb.toString();
}
}
@WebServlet("/api/user/*")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String path = req.getPathInfo(); // /1
Long id = Long.valueOf(path.substring(1));
// 模擬數據
Map<String, Object> address = new HashMap<>();
address.put("city", "Beijing");
address.put("street", "Chaoyang Road");
address.put("postcode", 100025);
Map<String, Object> user = new HashMap<>();
user.put("name", "Michael");
user.put("address", address);
// 輸出 JSON
resp.setContentType("application/json;charset=UTF-8");
resp.setCharacterEncoding("UTF-8");
try (PrintWriter pw = resp.getWriter()) {
pw.write(JsonUtil.toJson(user));
pw.flush();
}
}
}
| 庫 | 特點 | Maven 坐標 |
|---|---|---|
| Jackson | 高性能、功能全、Spring Boot 默認、支持流式/樹模型/數據綁定 | com.fasterxml.jackson.core:jackson-databind |
| Gson | Google 出品、API 簡潔、對 Kotlin 友好、適合 Android | com.google.code.gson:gson |
| JSON-B (Jakarta EE) | 標準化 API、多實現(Yasson、Johnzon)、CDI 集成 | jakarta.json.bind:jakarta.json.bind-api |
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
String json = mapper.writeValueAsString(userObject);
// 或直接返回對象,Spring MVC 自動轉換
@GetMapping("/api/user/{id}")
public User getUser(@PathVariable Long id) { return userService.find(id); }
application/json;charset=UTF-8,防止瀏覽器誤識為 HTML 執行腳本。)]}\',\n(GWT/Gmail 風格)。yyyy-MM-dd'T'HH:mm:ss.SSSZ),避免時區歧義。@JsonIgnore / @JsonManagedReference / @JsonBackReference 處理雙向關聯。JSON 以極簡語法、原生 JS 支持、廣泛語言生態成為 Web 數據交換事實標準。理解其格式本質、客戶端解析機制、服務端編碼邏輯,能幫你在選型、調試、性能優化、安全加固等環節做出專業決策。現代開發中,**客戶端優先 fetch + response.json(),服務端優先 Jackson/Gson 自動綁定**,手工編碼僅作教學或極端受限環境備選。