2014-02-20 44 views
0

我使用德爾福XE2,我有這樣的JSON結構創造:問題創建一個使用超對象或正確的JSON文件DBXJSON

[ 
    { 
     "Email": "[email protected]", 
     "MobileNumber": "", 
     "MobilePrefix": "", 
     "Name": "Laura", 
     "Fields": [ 
      { 
       "Description": "nominativo", 
       "Id": "1", 
       "Value": "Laura" 
      }, 
      { 
       "Description": "societa", 
       "Id": "2", 
       "Value": "" 
      }, 
      { 
       "Description": "idcontatto", 
       "Id": "3", 
       "Value": "0" 
      } 
     ] 
    }, 
    { 
     "Email": "[email protected]", 
     "MobileNumber": "", 
     "MobilePrefix": "", 
     "Name": "Paolo", 
     "Fields": [ 
      { 
       "Description": "nominativo", 
       "Id": "1", 
       "Value": "Paolo" 
      }, 
      { 
       "Description": "societa", 
       "Id": "2", 
       "Value": "" 
      }, 
      { 
       "Description": "idcontatto", 
       "Id": "3", 
       "Value": "1" 
      } 
     ] 
    } 
] 

我多次測試與超對象,但還沒有到達正確的結果因爲我得到的數組的第一個元素等於第二個。我的困難在於迭代和優化。這是我正在處理的代碼:

json := TSuperObject.Create;  
jsonArray:= TSuperObject.Create(stArray); 

json.S['Email'] := '[email protected]';  
json.S['MobileNumber'] := '';  
json.S['MobilePrefix'] := '';  
json.S['Name'] := 'Laura';  
json['Fields'] := SA([]);  
json_Fields:=SO;  
json_Fields.S['Description']:='nominativo';  
json_Fields.S['Id']:='1';  
json_Fields.S['Value']:='Laura';  
json.A['Fields'].Add(json_Fields);  
json_Fields:=SO;  
json_Fields.S['Description']:='societa';  
json_Fields.S['Id']:='2';  
json_Fields.S['Value']:='';  
json.A['Fields'].Add(json_Fields);  
//......other fields  
JsonArray.AsArray.Add(json); 

json.S['Email'] := '[email protected]';  
json.S['MobileNumber'] := '';  
json.S['MobilePrefix'] := '';  
json.S['Name'] := 'Paolo';  
json['Fields'] := SA([]);  
json_Fields:=SO;  
json_Fields.S['Description']:='nominativo';  
json_Fields.S['Id']:='1';  
json_Fields.S['Value']:='Paolo';  
json.A['Fields'].Add(json_Fields);  
json_Fields:=SO;  
json_Fields.S['Description']:='societa';  
json_Fields.S['Id']:='2';  
json_Fields.S['Value']:='';  
json.A['Fields'].Add(json_Fields);  
//......other fields  
JsonArray.AsArray.Add(json); 

jsonArray.SaveTo('json_mu.txt');  
+0

做什麼你試試,它在哪裏不起作用?當詢問你編寫的代碼時,你需要包含相關的代碼,或者更好的SSCCE –

+0

我已經編輯了問題並通過http://jsonlint.com/格式化了JSON,JSON將它驗證爲正確的JSON。 –

+0

請顯示您的*代碼*。 – Roddy

回答

1

您可以使用我們的record-based JSON serialization

首先定義一個記錄,幷包含所期望的數據項,和一個相應的動態數組:

type 
    TMyRecord: record 
    Name: string; 
    Email: string; 
    MobileNumber: string; 
    MobilePrefix: string; 
    Fields: array of record 
     Id: integer; 
     Description: string; 
     Value: string; 
    end; 
    end; 
    TMyRecordDynArray = array of TMyRecord; 

然後,你寄存器的記錄內容:

const // text description of the record layout 
    __TMyRecord = 'Name,Email,MobileNumber,MobilePrefix string '+ 
    'Fields[Id integer Description,Value string]'; 

    ... 

    TTextWriter.RegisterCustomJSONSerializerFromText(
    TypeInfo(TMyRecord),__TMyRecord); 

而且可以加載或保存數據從/到JSON:

var values: TMyRecordDynArray; 
    i: integer; 

    DynArrayLoadJSON(values,pointer(StringToUTF8(text)),TypeInfo(TMyRecordDynArray)); 
    for i := 0 to high(values) do 
    writeln('name: ',values[i].Name,' mobile: ',values[i].MobilePrefix,' fields count:',length(values[i].Fields)); 
    DynArraySaveJSON(values,TypeInfo(TMyRecordDynArray)); 

此JSON序列化程序將使用較少的內存t韓替代品,可能會更快,並且你有編譯時檢查屬性名稱。

這是從德爾福6可達XE5。

編輯:

例如,爲了填充數組:

var R: TMyRecordDynArray; 

SetLength(R,2); 
with R[0] do begin 
    Email := '[email protected]'; 
    Name := 'Laura'; 
    Setlength(Fields,3); 
    Fields[0].Description := 'nominativo'; 
    Fields[0].Id := 1; 
    Fields[0].Value := 'Laura'; 
    Fields[1].Description := 'societa'; 
    Fields[1].Id := 2; 
    Fields[2].Description := 'idcontatto'; 
    Fields[2].Id := 3; 
    Fields[2].Value := '0'; 
end; 
with R[1] do begin 
    Email := '[email protected]'; 
    Name := 'Paolo'; 
    Setlength(Fields,3); 
    Fields[0].Description := 'nominativo'; 
    Fields[0].Id := 1; 
    Fields[0].Value := 'Paolo'; 
    Fields[1].Description := 'societa'; 
    Fields[1].Id := 2; 
    Fields[2].Description := 'idcontatto'; 
    Fields[2].Id := 3; 
    Fields[2].Value := '1'; 
end; 

json := DynArraySaveJSON(R,TypeInfo(TMyRecordDynArray)); 

如果你不喜歡with聲明,到處可以添加R[0].。我懷疑這不是主要觀點。

我希望它能夠顯示使用編譯時結構代替定義爲文本的後期綁定屬性的好處(正如您使用的是SuperObject):在運行時,您不會期望任何有關屬性名稱的問題或一般邏輯。

如果您編寫了json_Fields.S['DescriptioM']:='nominativo',您將不會在IDE中看到任何錯誤,而Fields[0].DescriptioM := 'nominativo'將無法​​編譯。

如果要更改屬性名稱,你可以在IDE中重構它沒有在你的代碼忘了一個地方的任何機會 - 它不會編譯。

如果你的業務代碼中使用高層次德爾福結構,你將需要手動寫一些容易出錯的代碼,這些高水平的值轉換爲/從JSON,使用最交替librairies。而對於這樣的解決方案,您可以定義自己的值對象爲record,甚至可以在類型定義中添加一些方法,並直接在業務代碼中使用它,而不必考慮JSON持久層的實現細節。簡而言之:您是否想在業務代碼中爲您的JSON庫添加依賴項?聽起來像違反了我們試圖遵循的一些原則when defining Domain-Driven Design code

而且就在你的答案補充說,關於你的代碼的可讀性和可維護性的代碼進行比較。

還有所有未定義的字符串字段默認情況下用「'初始化(與任何動態數組一樣)的好處。

EDIT2:

正如Jan wrote in his own answer您可以使用超對象直接序列化記錄和動態數組,與我們的班。所以如果你不想使用SuperObject,我的建議是使用這個特性,並且使用Delphi的高級類型。請注意,SuperObject序列化可能會比我們的單元慢,並且不適用於舊版本的Delphi(而我們的單元與Delphi 6/7一起工作)。

+0

非常感謝您的建議,但我現在寧願使用superobject。 – user3319069

+0

@ user3319069我明白了。但是你在最初的請求中(在編輯和添加代碼之前)說你嘗試了幾個JSON庫,所以我只是提出了一個可行的替代方案。請參閱我對答案的編輯,也許您可​​能會發現使用高級別Delphi結構而不是後期綁定屬性的好處。 –

1

使用超對象:

定義德爾福數據結構與代替手動建立你的JSON結構工作,那麼使用的toJSON到德爾福對象轉換爲JSON結構:的

Uses SuperObject; 

type 
    FieldRec = record 
     ID: Integer; 
     Description, 
     Value: String; 
    end; 
    FieldArr = Array of FieldRec; 
    BaseRec = record 
     Fields: FieldArr; 
    end; 
    BaseArr = Array of BaseRec; 

    OutputObject = class 
     OutputData: BaseArr; 
    end; 

procedure TFrmAnotherJSONExample.FormShow(Sender: TObject); 
var 
    sObj: ISuperObject; 
    lFieldArr: FieldArr; 
    lBaseArr : BaseArr; 
    lOutputObject: OutputObject; 
begin 
    SetLength(lBaseArr,2); 
    SetLength(lFieldArr,3); 
    for i := 0 to 2 do 
    begin 
    lFieldArr[i].ID := 10*i; 
    lFieldArr[i].Description := 'Description' + IntToStr(lFieldArr[0].ID); 
    lFieldArr[i].Value := 'Name' + IntToStr(lFieldArr[0].ID); 
    end; 
    lBaseArr[0].Fields := lFieldArr; 
    for i := 0 to 2 do 
    begin 
    lFieldArr[i].ID := 100*i; 
    lFieldArr[i].Description := 'Description' + IntToStr(lFieldArr[0].ID); 
    lFieldArr[i].Value := 'Name' + IntToStr(lFieldArr[0].ID); 
    end; 
    lBaseArr[1].Fields := lFieldArr; 
    lOutputObject := OutputObject.Create; 
    lOutputObject.OutputData := lBaseArr; 
    sObj := lOutputObject.ToJSON; 
    lOutputObject.Free; 
    Memo1.Lines.Add(sObj.AsJSON(true)); 
end; 

輸出以上:

{ 
"OutputData": [ 
    { 
    "Fields": [ 
    { 
    "Description": "Description0", 
    "ID": 0, 
    "Value": "Name0" 
    },{ 
    "Description": "Description0", 
    "ID": 100, 
    "Value": "Name0" 
    },{ 
    "Description": "Description0", 
    "ID": 200, 
    "Value": "Name0" 
    }] 
    }, 
{ 
    "Fields": [ 
    { 
    "Description": "Description0", 
    "ID": 0, 
    "Value": "Name0" 
    },{ 
    "Description": "Description0", 
    "ID": 100, 
    "Value": "Name0" 
    },{ 
    "Description": "Description0", 
    "ID": 200, 
    "Value": "Name0" 
    }] 
    }] 
} 

這樣你得到命名的數組,我假設沒問題(我會推薦它)。
此外,它具有定義JSON對象的外部{}。

新增:對發佈我看到,我已經忘記了,以填補電子郵件移動電話號碼等領域,但現在這是微不足道的,我走了以後把作爲練習讀者;-)