2026/04/21

【Delphi 現代化轉型】Day 4:Horse 資料庫神操作 -- 使用 ADO 和 FireDAC 建立 JSON

作者:吳祐賓 

 


 

 

先說結論 

 

給你的評估參考,除非你前後端完全使用 Delphi 開發,否則不建議使用內建的 FireDAC 轉 JSON 的任何工具。但前後端使用 Delphi 開發也不用太到 JSON 轉換才對。

 

使用我公開的 EdenDBXJsonHelper.pas 單元,可以讓你在 Delphi 現代化轉型少走很多彎路 

 


本文開始


使用 Day 3 的程式碼範例,並建立 DataModule,將 ADO 和 FireDAC 元件帶入,並連結好你的資料庫,如果完成,畫面應該像這樣:

 


 

注意!TFDStanStorageJSONLink 是 FireDAC 轉出 JSON 必須使用的元件,若不拉進來,使用 FD 內建的函式會因跳出例外而出錯

 

 

建立 Horse API 取得 FireDAC 資料集


回到 horse 專案的主單元,設計取得 FireDAC 資料集,程式碼非常簡單,資料庫的常規操作即可



uses
  Horse, System.Classes, Winapi.ActiveX, FireDAC.Stan.Intf;

THorse.Get('/firedac_emp',
  procedure(Req: THorseRequest; Res: THorseResponse)
  var
    LDM: TDataModule1;
    LStream: TStringStream;
  begin
    // 1. 初始化 COM (重要:Horse 是多執行緒,MSSQL 等驅動需要此步驟)
    CoInitialize(nil);
    
    LDM := TDataModule1.Create(nil);
    LStream := TStringStream.Create('', TEncoding.UTF8);
    try
      // 2. 執行 SQL 取得資料
      LDM.FDQuery1.SQL.Text := 'SELECT * FROM employee';
      LDM.FDQuery1.Open;
      
      // 3. 使用 FireDAC 內建方法將 DataSet 轉入 Stream (格式選 sfJSON)
      LDM.FDQuery1.SaveToStream(LStream, sfJSON);
      
      // 4. 回傳字串內容
      Res.Send(LStream.DataString);
    finally
      LStream.Free;
      LDM.Free;
      // 5. 釋放 COM
      CoUninitialize;
    end;
  end);


這裡要留意的是,以 MSSQL 為例,FireDAC MSSQL Driver 是呼叫 COM 來操作,所以必須初始化 COM 與釋放 COM (CoInitialize(nil) and CoUninitialize)

 

轉換 JSON 原理是透過 TStringtream 進行轉換,最後交由 Response 送回客戶端

 

 

我完全不推 FireDAC 原生作法

 

上述程式碼看似「完成了」,但你打開瀏覽器看結果,你會發現兩個大問題:

1. 冗餘結構 (The FDBS Mess):
 

FireDAC 產出的 JSON 包含了大量的 Metadata(欄位長度、型態等),這對 Delphi 來說是瑰寶,但對 Web 前端(JavaScript)是垃圾。

前端工程師還得自己進到 FDBS -> Manager -> Table -> Rows 裡面去找資料,包準他們會一邊寫一邊碎碎念。



2. 惡夢般的日期格式:
 

輸出結果中的日期會長這樣:19930809T000000.000。
 

這是 ISO 8601 的壓縮格式,JS 的 new Date() 根本吃不進去。這只有 Delphi 客戶端 + FireDAC 才能「無痛」解開的格式,放到現代 Web 專案中,負責串接 API 的乙方會恨死你。 

 

FireDAC 預設轉出的 JSON 格式


 

官方預設 JSON 帶有許多 Delphi 專用的 MetaData
 

日期格式還是 ISO 8601 的壓縮格式



建立 Horse API 取得 ADO 資料集


就是一開始建立的 TADOConnection 和 TADOQuery 元件,搭配下載的 EdenDBXJsonHelper.pas 單元後程式碼就變這樣:

 


uses DBXJSONCommon, EdenDBXJsonHelper;

THorse.Get('/ado_emp',
  procedure(Req: THorseRequest; Res: THorseResponse)
  begin
    // 初始化 COM
    CoInitialize(nil);
    var LDM := TDataModule1.Create(nil);
    try
      LDM.ADOQuery1.SQL.Text := 'SELECT * FROM employee';
      LDM.ADOQuery1.Open;
      Res.Send(TDBXJSONTools.DataSetToJSONArray(LDM.ADOQuery1).ToJson);
    finally
      LDM.Free;
      // 釋放 COM
      CoUninitialize;
    end;
  end);

 

簡單好上手,一段話就將資料集直接轉為 JS 可以直接使用的 JSON 格式,連刁鑽的日期格式也使用 ISO 8601 擴展模式,不論是 MSSQL 資料庫或 JS 前端框架,都是無痛使用

 

這只是拿前朝主流 ADO 元件來使用,但 BDE、IBX、DBX、FireDAC 等 TDataSet 繼承下來的資料集也可一併套用! 


符合現代標準化 JS 格式


日期採用 ISO 8601 擴展格式 (Extended Format)

 

 這才是程式設計極簡的中心思想,在適合的地方,就用適合的工具,即為現代化轉型思路王道

 

沒有留言:

張貼留言