2017-09-15 42 views
0

我正在使用Delphi東京10.2更新1和RESTRequest,RESTResponse和RESTClient組件來與REST服務器進行通信。這是我第一次嘗試使用REST/JSON。Delphi/REST/JSON

我已成功發送登錄請求(POST)並收到了預期的響應(GUID)。然後我使用GUID來執行各種其他請求(GET)。其中兩個請求發回一個空文件和文檔JSON模板,然後我必須填充。這是我卡住的地方。我不確定在JSON對象中更新屬性值的最佳方法。

下面是空的JSON文件模板我找回:

{ 
    "boxId": 0, 
    "changedBy": 0, 
    "customSort": "", 
    "dateChanged": "1990-01-01T00:00:00", 
    "dateStarted": "1990-01-01T00:00:00", 
    "destruction": "1990-01-01T00:00:00", 
    "documentCount": 0, 
    "documents": { 
    "TotalCount": 0, 
    "Collection": [ 

    ] 
    }, 
    "extraData": { 
    "TotalCount": 0, 
    "Collection": [ 

    ] 
    }, 
    "fieldDefs": { 
    "TotalCount": 0, 
    "Collection": null 
    }, 
    "field": [ 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "", 
    "" 
    ], 
    "fileId": 0, 
    "filePtr": 0, 
    "id": 0, 
    "isIndexed": false, 
    "keyValue": "", 
    "keyVisualValue": "", 
    "labelPrinted": "1990-01-01T00:00:00", 
    "lineItems": { 
    "TotalCount": 0, 
    "Collection": [ 

    ] 
    }, 
    "notes": "", 
    "objectType": 5, 
    "projectId": 0, 
    "routeInfo": null, 
    "routingDoc": null, 
    "remoteId": 0, 
    "saveNotesOnly": false, 
    "saveStyle": -999, 
    "status": 1, 
    "syncFlag": 0, 
    "totalDocumentCount": 0, 
    "viewerContext": 0 
} 

在Python填充字段屬性數組中的前兩個值我只是會做:

inc_filetemplate = json.loads(requests.get(NEWFILE_string).text) 
inc_doctemplate = json.loads(requests.get(NEWDOC_string).text) 
filetemplate = inc_filetemplate 
doctemplate = inc_doctemplate 
filetemplate['field'][1] = dcn 
filetemplate['field'][2] = batchname 

EASY !!!! ;)

用Delphi做這件事的最好方法是什麼?

我可以從「字段」數組(這個例子中的前兩個項目恰好爲空)獲取值。只是不確定爲這些項目設置值的最佳方式。

這是我已經開始:

procedure PopulateFileTemplate(const AFileTemplate: String); 
var 
    JO: TJSONObject; 
    JOPair: TJSONPair; 
    JOArray: TJSONArray; 
    FieldDCN: String; 
    FieldBatchName: String; 

begin 
    JO := TJSONObject.ParseJSONValue(AFileTemplate) as TJSONObject; 

    try 
    if JO = nil then 
    begin 
     MessageDlg('Unable to parse JSON file template.', mtError, [mbOK], 0); 

     Exit; 
    end; 

    JOArray := JO.Get('field').JsonValue as TJSONArray; 
    FieldDCN := JOArray.Items[0].Value; 
    FieldBatchName := JOArray.Items[1].Value; 

    Memo1.Lines.Add('The old value of DCN is: ' + FieldDCN); 
    Memo1.Lines.Add('The old value of BatchName is: ' + FieldBatchName); 

    // Best way to set Values here??????? 

    Memo1.Lines.Add('The new value of DCN is: ' + FieldDCN); 
    Memo1.Lines.Add('The new value of BatchName is: ' + FieldBatchName); 
    finally 
    JO.Free; 
    end; 
end; 
+0

您需要選擇一個JSON庫,例如超級對象。 –

+0

德爾福也有內置於RTL的自己的[JSON框架](http://docwiki.embarcadero.com/RADStudio/en/JSON)。 –

+0

我已經看過並使用內置於RTL的JSON框架。但是,無論我沒有做正確的事情,還是無法像使用Python一樣直接設置JSON屬性值。我會繼續玩JsonTextReader和JsonTextWriter。 – klbass68

回答

0

TJSONArray.Items[]屬性返回TJSONValue,它在你的例子是,因爲fields字符串數組TJSONString對象。

TJSONArray實際上並未設計爲允許修改陣列中的個已有個對象。您可以將新對象添加到數組末尾,並從數組中刪除任意對象,但不能在任意索引處插入新對象,或者用新對象替換現有對象。

最接近這種功能的是構建一個TList<TJSONValue>,其中包含所需的對象,然後將它傳遞給TJSONArray.SetElements()。不理想。

TJSONString沒有任何方法或屬性來編輯其string值(TJSONString.AddChar()除外)。

你可以嘗試使用訪問/輔助類來訪問受保護的TJSONString.FStrBuffer成員,然後修改它的內容需要:

type 
    TJSONStringAccess = class(TJSONString) 
    end; 

procedure SetJSONStringValue(JSONValue: TJSONString; const S: string); 
begin 
    with TJSONStringAccess(JSONValue) do 
    begin 
    FStrBuffer.Clear; 
    FStrBuffer.Append(S); 
    end; 
end; 

procedure PopulateFileTemplate(const AFileTemplate: String); 
var 
    JO: TJSONObject; 
    JOPair: TJSONPair; 
    JOArray: TJSONArray; 
    FieldDCN: TJSONString; 
    FieldBatchName: TJSONString; 
begin 
    JO := TJSONObject.ParseJSONValue(AFileTemplate) as TJSONObject; 
    if JO = nil then 
    begin 
    MessageDlg('Unable to parse JSON file template.', mtError, [mbOK], 0); 
    Exit; 
    end; 
    try 
    JOArray := JO.Get('field').JsonValue as TJSONArray; 
    FieldDCN := JOArray.Items[0] as TJSONString; 
    FieldBatchName := JOArray.Items[1] as TJSONString; 

    Memo1.Lines.Add('The old value of DCN is: ' + FieldDCN.Value); 
    Memo1.Lines.Add('The old value of BatchName is: ' + FieldBatchName.Value); 

    SetJSONStringValue(FieldDCN, '...'); 
    SetJSONStringValue(FieldBatchName, '...'); 

    Memo1.Lines.Add('The new value of DCN is: ' + FieldDCN.Value); 
    Memo1.Lines.Add('The new value of BatchName is: ' + FieldBatchName.Value); 
    finally 
    JO.Free; 
    end; 
end; 

type 
    TJSONStringHelper = helper class for TJSONString 
    procedure SetValue(const S: string); 
    end; 

procedure TJSONStringHelper.SetValue(const S: string); 
begin 
    Self.FStrBuffer.Clear; 
    Self.FStrBuffer.Append(S); 
end; 

procedure PopulateFileTemplate(const AFileTemplate: String); 
var 
    JO: TJSONObject; 
    JOPair: TJSONPair; 
    JOArray: TJSONArray; 
    FieldDCN: TJSONString; 
    FieldBatchName: TJSONString; 
begin 
    JO := TJSONObject.ParseJSONValue(AFileTemplate) as TJSONObject; 
    if JO = nil then 
    begin 
    MessageDlg('Unable to parse JSON file template.', mtError, [mbOK], 0); 
    Exit; 
    end; 
    try 
    JOArray := JO.Get('field').JsonValue as TJSONArray; 
    FieldDCN := JOArray.Items[0] as TJSONString; 
    FieldBatchName := JOArray.Items[1] as TJSONString; 

    Memo1.Lines.Add('The old value of DCN is: ' + FieldDCN.Value); 
    Memo1.Lines.Add('The old value of BatchName is: ' + FieldBatchName.Value); 

    FieldDCN.SetValue('...'); 
    FieldBatchName.SetValue('...'); 

    Memo1.Lines.Add('The new value of DCN is: ' + FieldDCN.Value); 
    Memo1.Lines.Add('The new value of BatchName is: ' + FieldBatchName.Value); 
    finally 
    JO.Free; 
    end; 
end; 

否則,考慮切換到第3本機支持編輯值的第三方JSON庫。如SuperObject

+0

謝謝你。看起來像SuperObject可能是更好的選擇。在我的研究中,我確實看到有人使用它。現在下載。再次感謝! – klbass68