首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP JSON 深度解析:編碼、解碼與跨域應用實戰

     編輯:PHP 相關知識

為什麼選擇 JSON 而非 XML?

在 AJAX 技術普及的早期,XML 是數據交換的標準格式。然而,XML 的樹狀結構雖然靈活,但在 JavaScript 端解析卻相對繁瑣,需要操作 DOM 樹、節點遍歷,代碼冗長且易出錯。JSON (JavaScript Object Notation) 的出現徹底改變了這一局面:它本質上是 JavaScript 物件字面量語法的子集,原生支持於 JS 中,解析速度極快,數據體積更小,結構清晰易讀,迅速成為 Web API 的事實標準。

PHP 內置 JSON 支持 (PHP 5.2+)

自 PHP 5.2 起,核心擴展內置了 JSON 功能,提供兩個核心函數,用法與 serialize/unserialize 極為相似:

  • json_encode($value):將 PHP 變數(陣列、物件)編碼為 JSON 字符串。
  • json_decode($json, $assoc = false):將 JSON 字符串解碼為 PHP 變數。第二個參數為 true 時返回關聯陣列,否則返回 stdClass 物件。

編碼實戰:處理中文與編碼陷阱

核心限制: json_encode 強制要求輸入為 UTF-8 編碼。若 PHP 源文件或數據庫編碼為 GB2312/GBK,直接編碼包含中文的數據會導致中文變為 null 或輸出 Unicode 轉義序列 (如 \u4e2d\u6587)。

<?php
// 示例數據
$arr = array(
    'name' => '陳毅鑫',
    'nick' => '深空',
    'contact' => array(
        'email' => 'shenkong@qq.com',
        'website' => 'https://www.example.com'
    )
);

// 情況一:源文件為 UTF-8 (推薦現代開發標準)
$json_string = json_encode($arr);
echo $json_string;
// 輸出: {"name":"\u9648\u6bc5\u946b","nick":"\u6df1\u7a7a","contact":{"email":"shenkong@qq.com","website":"http:\/\/www.example.com"}}
// 註:預設會轉義 Unicode,PHP 5.4+ 可用 JSON_UNESCAPED_UNICODE 保持中文可讀

// 情況二:源文件為 GB2312 - 必須轉碼
// $arr_utf8 = array_map('iconv', $arr, ['gb2312', 'utf-8']); // 簡寫需遞歸處理多維陣列
// $json_string = json_encode($arr_utf8);
?>

解碼實戰:物件與陣列互轉

<?php
$json_string = '{"name":"\u9648\u6bc5\u946b","nick":"\u6df1\u7a7a","contact":{"email":"shenkong@qq.com","website":"http:\/\/www.example.com"}}';

// 1. 解碼為物件 (預設)
$obj = json_decode($json_string);
echo $obj->name; // 輸出: 陳毅鑫 (自動解碼 Unicode)
echo $obj->contact->email;

// 2. 解碼為關聯陣列 (推薦,操作更直觀)
$arr = json_decode($json_string, true); // 關鍵參數 true
echo $arr['name'];
echo $arr['contact']['website'];

// 3. 錯誤處理 (PHP 5.3+)
if (json_last_error() !== JSON_ERROR_NONE) {
    echo 'JSON 解析錯誤: ' . json_last_error_msg();
}
?>

進階應用:JSONP 實現跨域數據調用

受瀏覽器同源策略限制,Ajax 無法直接請求不同域名下的接口。JSONP (JSON with Padding) 是一種經典的跨域解決方案,利用 <script> 標籤不受同源策略限制的特性。

原理圖解

  1. 前端定義全局回調函數 getProfile(data)。
  2. 動態創建 <script src="https://api.other.com/profile.php?callback=getProfile"></script>。
  3. 後端接收 callback 參數,輸出 getProfile({...json數據...})。
  4. 瀏覽器執行腳本,觸發前端回調,獲得數據。

代碼實現

前端頁面 (index.html)

<!DOCTYPE html>
<html>
<body>
<div id="nick">加載中...</div>

<script>
function getProfile(str) {
    // str 已經是 JS 物件 (若後端輸出正確)
    document.getElementById('nick').innerHTML = '暱稱:' + str.nick;
}
// 動態插入 script 標籤發起請求
var script = document.createElement('script');
script.src = 'https://www.phpfans.org/demo/profile.php?callback=getProfile';
document.head.appendChild(script);
</script>
</body>
</html>

後端接口 (profile.php)

<?php
$arr = array(
    'name' => '陳毅鑫',
    'nick' => '深空',
    'contact' => array(
        'email' => 'shenkong@qq.com',
        'website' => 'https://www.bkjia.com'
    )
);

$json_string = json_encode($arr);

// 關鍵:獲取回調函數名,包裹 JSON 字符串
$callback = isset($_GET['callback']) ? $_GET['callback'] : 'callback';

// 安全過濾:防止 XSS,僅允許字母數字下劃線
if (!preg_match('/^[a-zA-Z0-9_]+$/', $callback)) {
    exit('Invalid callback');
}

// 輸出 JavaScript 語句
header('Content-Type: application/javascript; charset=utf-8');
echo $callback . '(' . $json_string . ');';
?>

現代替代方案:CORS (Cross-Origin Resource Sharing)

雖然 JSONP 簡單易用,但僅支持 GET 請求,且存在安全隱患 (CSRF、腳本注入)。現代開發強烈推薦使用 CORS:

  • 後端設置 Header:header('Access-Control-Allow-Origin: *'); (或指定域名)
  • 支持所有 HTTP 動詞 (GET, POST, PUT, DELETE 等)
  • 安全性更高,瀏覽器原生支持,無需注入腳本

總結

JSON 以其輕量、原生兼容 JS、易於解析的優勢,成為現代 Web 數據交換的核心。PHP 內置函數讓編解碼極為簡單,但編碼統一 (UTF-8) 是避坑關鍵。跨域需求下,理解 JSONP 原理有助於掌握 Web 通信本質,但生產環境請優先採用 CORS 標準。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved