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

PHP 生成格式化巢狀 JSON:json_encode 進階技巧與自定義縮排函數

     編輯:PHP 相關知識

目標 JSON 結構

{
    "aa": [
        {"Id": "0", "title": "標題"},
        {"Id": "1", "title": "標題"}
    ],
    "bb": [
        {"Id": "2", "title": "標題"},
        {"Id": "3", "title": "標題"}
    ]
}

現代 PHP 內建方案(PHP 5.4+)

<?php
$data = [
    'aa' => [
        ['Id' => 0, 'title' => '標題'],
        ['Id' => 1, 'title' => '標題'],
    ],
    'bb' => [
        ['Id' => 2, 'title' => '標題'],
        ['Id' => 3, 'title' => '標題'],
    ],
];

// 核心參數說明
$options = JSON_PRETTY_PRINT      // 縮排美化
         | JSON_UNESCAPED_UNICODE // 中文不轉義
         | JSON_UNESCAPED_SLASHES // 不轉義斜線
         | JSON_NUMERIC_CHECK;    // 數字字符串轉數字

header('Content-Type: application/json; charset=utf-8');
echo json_encode($data, $options);

輸出結果

{
    "aa": [
        {
            "Id": 0,
            "title": "標題"
        },
        {
            "Id": 1,
            "title": "標題"
        }
    ],
    "bb": [
        {
            "Id": 2,
            "title": "標題"
        },
        {
            "Id": 3,
            "title": "標題"
        }
    ]
}

舊版本兼容方案:自定義縮排函數

PHP 5.3 及以下無 JSON_PRETTY_PRINT,需手動格式化:

<?php
function jsonFormat(mixed $data, string $indent = '    '): string
{
    // 1. 遞歸 URL 編碼保護中文
    array_walk_recursive($data, function (&$val) {
        if (is_string($val)) $val = urlencode($val);
    });

    // 2. 編碼
    $json = json_encode($data);

    // 3. 解碼還原中文
    $json = urldecode($json);

    // 4. 手動縮排
    $result = '';
    $pos = 0;
    $len = strlen($json);
    $newline = "\n";
    $inString = false;
    $escape = false;

    for ($i = 0; $i < $len; $i++) {
        $char = $json[$i];

        // 處理字符串邊界
        if ($char === '"' && !$escape) {
            $inString = !$inString;
        }
        $escape = ($char === '\\' && !$escape);

        // 結構字符處理
        if (!$inString) {
            if ($char === '}' || $char === ']') {
                $result .= $newline;
                $pos--;
                $result .= str_repeat($indent, $pos);
            }
        }

        $result .= $char;

        if (!$inString) {
            if ($char === ',' || $char === '{' || $char === '[') {
                $result .= $newline;
                if ($char === '{' || $char === '[') {
                    $pos++;
                }
                $result .= str_repeat($indent, $pos);
            }
        }
    }

    return $result;
}

// 使用
echo jsonFormat($data);

進階技巧

1. 數字字符串自動轉數字

$data = ['price' => '199.00', 'count' => '10'];
echo json_encode($data, JSON_NUMERIC_CHECK);
// {"price":199.0,"count":10}

2. 大數字保持字符串(避免 JS 精度丟失)

$data = ['order_id' => '1234567890123456789'];
// 不加 JSON_NUMERIC_CHECK,或手動轉型
echo json_encode($data); // {"order_id":"1234567890123456789"}

3. 自定義序列化(實現 JsonSerializable)

class User implements JsonSerializable
{
    private string $name;
    private string $email; // 敏感字段

    public function __construct(string $name, string $email)
    {
        $this->name = $name;
        $this->email = $email;
    }

    public function jsonSerialize(): array
    {
        return [
            'name' => $this->name,
            'email_masked' => $this->maskEmail($this->email),
        ];
    }

    private function maskEmail(string $email): string
    {
        [$local, $domain] = explode('@', $email);
        return substr($local, 0, 1) . '***' . '@' . $domain;
    }
}

echo json_encode(new User('張三', 'zhangsan@example.com'), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);

4. 流式輸出大型 JSON(節省記憶體)

function streamJsonArray(iterable $items): Generator
{
    yield '[';
    $first = true;
    foreach ($items as $item) {
        if (!$first) yield ',';
        yield json_encode($item, JSON_UNESCAPED_UNICODE);
        $first = false;
    }
    yield ']';
}

// 直接輸出到瀏覽器/文件
header('Content-Type: application/json');
foreach (streamJsonArray($hugeDataset) as $chunk) {
    echo $chunk;
    @ob_flush(); @flush();
}

常見問題速查表

問題解決方案
中文變 \uXXXX加 JSON_UNESCAPED_UNICODE
斜線變 \/加 JSON_UNESCAPED_SLASHES
浮點數精度丟失用字符串存儲或 number_format
循環引用報錯實現 JsonSerializable 控制輸出
大數據記憶體溢出流式生成器分塊輸出

現代 PHP 專案直接使用 json_encode 組合旗標即可滿足 99% 場景;僅在極舊環境或特殊串流需求時才需自定義格式化邏輯。

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