為什麼先把「寫法」講好
資料每天都可能變,但寫法要固定。固定的寫法能讓介面設計、測試、自動化與協作變簡單:欄位看名字就懂、錯誤一眼能判斷、時間不用猜。今天把三件事定清楚,後面都照這套走。
一、命名規則(看名字就懂)
欄位命名(JSON):
•用小駝峰:routeId, stopId, stopName, lat, lon, direction, estimateSeconds, updateTime。
•布林開頭用 is/has:isLastBus, hasWheelchair。
•清單用複數:routes, stops。
•多語包在子物件:stopName.zh, stopName.en。
•單位寫在欄位名:distanceMeters, estimateSeconds。
•固定與即時共用同名鍵:routeId, stopId。
URL/資源命名:小寫、kebab-case:/bus/routes, /bus/stops, /bus/eta;過濾用查詢參數:/bus/eta?routeId=307&stopId=12345。
方向與枚舉:direction 0=去程、1=返程(文件明寫);stopStatus 用可讀字串:normal / last / suspended / noData。
好/壞對照:✅ estimateSeconds, updateTime, stopName.zh;❌ ETA, val, time(看不出單位或意義)。
二、錯誤訊息格式
固定欄位(每種錯誤都有):code(短代碼)、message(中文一句話)、status(HTTP 數字)、timestamp(ISO 8601、含時區)、traceId(追蹤用)、userHint(下一步建議)、details(選填,補充脈絡)。
常見情境的用語:
•缺少必要參數(400):missing_parameter;「缺少必要參數:routeId。」;「請帶上 routeId 與 stopId。」
•查無資料(404):not_found;「查無符合的路線或站點。」;「確認 routeId、stopId 是否正確。」
•金鑰錯誤/無權限(401/403):unauthorized/forbidden;「金鑰無效或未提供。」
•查太頻繁(429):rate_limit_exceeded;「查詢過於頻繁,請稍後再試。」(details 可含 retryAfterSeconds)
•來源逾時/暫停(504/503):upstream_timeout/service_unavailable;「資料來源回應逾時。」
原則:固定結構與用語;message 給人看、code 給機器用、userHint 告訴下一步。
三、時間格式(ISO 8601),不用猜就對齊
全用 YYYY-MM-DDThh:mm:ss+08:00(含時區)。即時資料必帶 updateTime;固定資料有版本或公告時間也用同格式。代表「持續時間」的欄位用秒數整數(estimateSeconds: 180)。顯示層再把秒數轉成「x 分鐘/即將進站」,來源保持秒。
好/壞對照:
✅ updateTime: "2025-10-20T08:29:00+08:00";estimateSeconds: 45。
❌ updateTime: "2025/10/20 08:29"(無時區)、eta: "約 3 分鐘"(不利機器處理)。
固定與即時一致:兩邊都用 updateTime 表示「這筆資料是什麼時候算出來的」。需要排序或比較新舊時,只看 updateTime。