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

JSON 數據結構詳解:無序對象 vs 有序數組,PHP json_encode 陷阱與微信接口實戰

     編輯:PHP 相關知識

JSON 兩大核心結構

結構JSON 形式對應 PHP 類型特點
無序對象{"key": "value", ...}關聯數組 ['key' => 'value']鍵值對、鍵唯一、無順序保證
有序數組["item1", "item2", ...]索引數組 [0 => 'item1', 1 => 'item2']有序列表、允許重複、索引連續

微信自定義菜單接口實戰:為什麼 json_encode 輸出不對?

期望 JSON(文檔示例)

{
  "button": [
    {"type": "click", "name": "今日歌曲", "key": "V1001_TODAY_MUSIC"},
    {"type": "click", "name": "歌手簡介", "key": "V1001_TODAY_SINGER"},
    {"name": "菜單", "sub_button": [
      {"type": "view", "name": "搜索", "url": "https://www.soso.com/"},
      {"type": "view", "name": "視頻", "url": "https://v.qq.com/"},
      {"type": "click", "name": "贊一下我們", "key": "V1001_GOOD"}
    ]}
  ]
}

關鍵點:button 是**有序數組**,每個元素是**對象**;sub_button 也是**有序數組**。

PHP 陷阱:關聯數組被編碼為對象

$menu = [
  'button' => [
    1 => ['type' => 'click', 'name' => '今日歌曲', 'key' => 'V1001_TODAY_MUSIC'],
    2 => ['type' => 'click', 'name' => '歌手簡介', 'key' => 'V1001_TODAY_SINGER'],
    3 => ['name' => '菜單', 'sub_button' => [
      ['type' => 'view', 'name' => '搜索', 'url' => 'https://www.soso.com/'],
      ['type' => 'view', 'name' => '視頻', 'url' => 'https://v.qq.com/'],
      ['type' => 'click', 'name' => '贊一下我們', 'key' => 'V1001_GOOD'],
    ]]
  ]
];
echo json_encode($menu);

實際輸出(錯誤)

{
  "button": {
    "1": {"type": "click", "name": "今日歌曲", "key": "V1001_TODAY_MUSIC"},
    "2": {"type": "click", "name": "歌手簡介", "key": "V1001_TODAY_SINGER"},
    "3": {"name": "菜單", "sub_button": [...]}
  }
}

button 變成了**對象**(鍵為 "1","2","3"),而非**數組**。微信接口拒絕此格式。

根因:PHP 數組判斷規則

  • PHP 數組同時是「關聯數組」與「索引數組」。
  • json_encode 判斷邏輯:若鍵為連續整數從 0 開始,編碼為數組;否則編碼為對象。
  • 上例中鍵為 1、2、3(非從 0 開始),故編碼為對象。

修正方案:使用 array_values() 重建索引

$menu = [
  'button' => array_values([ // 強制重建 0-based 索引
    ['type' => 'click', 'name' => '今日歌曲', 'key' => 'V1001_TODAY_MUSIC'],
    ['type' => 'click', 'name' => '歌手簡介', 'key' => 'V1001_TODAY_SINGER'],
    ['name' => '菜單', 'sub_button' => array_values([
      ['type' => 'view', 'name' => '搜索', 'url' => 'https://www.soso.com/'],
      ['type' => 'view', 'name' => '視頻', 'url' => 'https://v.qq.com/'],
      ['type' => 'click', 'name' => '贊一下我們', 'key' => 'V1001_GOOD'],
    ])]
  ])
];
echo json_encode($menu, JSON_UNESCAPED_UNICODE);

輸出(正確)

{
  "button": [
    {"type": "click", "name": "今日歌曲", "key": "V1001_TODAY_MUSIC"},
    {"type": "click", "name": "歌手簡介", "key": "V1001_TODAY_SINGER"},
    {"name": "菜單", "sub_button": [
      {"type": "view", "name": "搜索", "url": "https://www.soso.com/"},
      {"type": "view", "name": "視頻", "url": "https://v.qq.com/"},
      {"type": "click", "name": "贊一下我們", "key": "V1001_GOOD"}
    ]}
  ]
}

最佳實踐清單

  1. 構建數組時直接用 [] 短語法,避免手寫數字鍵。
  2. 嵌套層級均用 array_values() 保證 0-based 索引,特別是動態構建的列表。
  3. 輸出時加 JSON_UNESCAPED_UNICODE:中文不轉 \uXXXX,可讀性強、體積略小。
  4. API 協議文檔優先:仔細閱讀字段是「對象」還是「數組」,對應 PHP 關聯/索引數組。
  5. 單元測試驗證 JSON 結構:json_decode($output, true) 斷言鍵類型與順序。

擴展:JSON_FORCE_OBJECT 強制對象

$arr = ['a', 'b', 'c'];
echo json_encode($arr);                    // ["a","b","c"]
echo json_encode($arr, JSON_FORCE_OBJECT); // {"0":"a","1":"b","2":"c"}

適用於接口要求對象但數據本質為列表的罕見場景。

總結

JSON「無序對象」對應 PHP 關聯數組,「有序數組」對應 PHP 0-based 索引數組。json_encode 以「鍵是否為連續 0-based 整數」判斷輸出類型。構建微信等嚴格結構的 API 請求時,**務必對所有列表層級使用 array_values() 重建索引**,並加 JSON_UNESCAPED_UNICODE 輸出。

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