Delphi用QJSON解析JSON格式的數(shù)據(jù)

字號:


    本來用superobject來解析JSON已經(jīng)夠用了,可惜這個(gè)東東不能在移動(dòng)段使用,于是找到QJSON來處理。
    這是一個(gè)國內(nèi)高手寫開源免費(fèi)的東西,贊一個(gè)。
    加入數(shù)據(jù)如下:
    {"message":"ok","status":"1","state":"3","data":
    [{"time":"2012-07-07 13:35:14","context":"客戶已簽收"},
    {"time":"2012-07-07 09:10:10","context":"離開 [北京石景山營業(yè)廳] 派送中,遞送員
    [溫],電話[]"},
    {"time":"2012-07-06 19:46:38","context":"到達(dá) [北京石景山營業(yè)廳]"},
    {"time":"2012-07-06 15:22:32","context":"離開 [北京石景山營業(yè)廳] 派送中,遞送員
    [溫],電話[]"},
    {"time":"2012-07-06 15:05:00","context":"到達(dá) [北京石景山營業(yè)廳]"},
    {"time":"2012-07-06 13:37:52","context":"離開 [北京_同城中轉(zhuǎn)站] 發(fā)往 [北京石景山
    營業(yè)廳]"},
    {"time":"2012-07-06 12:54:41","context":"到達(dá) [北京_同城中轉(zhuǎn)站]"},
    {"time":"2012-07-06 11:11:03","context":"離開 [北京運(yùn)轉(zhuǎn)中心駐站班組] 發(fā)往 [北京_
    同城中轉(zhuǎn)站]"},
    {"time":"2012-07-06 10:43:21","context":"到達(dá) [北京運(yùn)轉(zhuǎn)中心駐站班組]"},
    {"time":"2012-07-05 21:18:53","context":"離開 [福建_廈門支公司] 發(fā)往 [北京運(yùn)轉(zhuǎn)中
    心_航空]"},
    {"time":"2012-07-05 20:07:27","context":"已取件,到達(dá) [福建_廈門支公司]"}
    ]}
    用QJSON解析如下:
    procedure TForm15.Button1Click(Sender: TObject);
    var
    aqjson,aqjsonarr : TQJSON;
    i : Integer;
    stime, scontext : string;
    begin
    aqjson := TQJSON.Create;
    aqjson.parse(memo1.lines.text);
    if aqjson.ValueByName('message', '') = 'ok' then
    begin
    memo2.Clear;
    aqjsonarr := aqjson.ItemByName('data');
    for i := 0 to aqjsonarr.Count - 1 do
    begin
    stime := aqjsonarr.Items[i].ValueByName('time', '');
    scontext := aqjsonarr.Items[i].ValueByName('context', '');
    Memo2.Lines.Add(stime+'----'+scontext);
    end;
    end;
    end;
    可以看到QJSON的解析還是很方便的。
    不過這種格式存在大量冗余數(shù)據(jù)——每個(gè)數(shù)據(jù)項(xiàng)都攜帶了字段信息,其實(shí)可以只返回一次字段信息即可。
    數(shù)據(jù)精簡如下:
    {"message":"ok","status":"1","state":"3","data":
    ["2012-07-07 13:35:14","客戶已簽收",
    "2012-07-07 09:10:10","離開 [北京石景山營業(yè)廳] 派送中,遞送員[溫],電話[]",
    ]}
    可以看到數(shù)組里面的串不再是JSON格式(Key:Value)的了,這時(shí)不能再使用ValueByName,而直接使用Value。
    procedure TForm15.Button2Click(Sender: TObject);
    var
    aqjson,aqjsonarr : TQJSON;
    i : Integer;
    stime, scontext : string;
    begin
    aqjson := TQJSON.Create;
    aqjson.parse(memo3.lines.text);
    if aqjson.ValueByName('message', '') = 'ok' then
    begin
    memo2.Clear;
    aqjsonarr := aqjson.ItemByName('data');
    for i := 0 to aqjsonarr.Count - 1 do
    begin
    stime := aqjsonarr.Items[i].ValueByName('time', '');
    scontext := aqjsonarr.Items[i].ToString;
    Memo2.Lines.Add(stime+'----'+scontext);
    end;
    end;
    end;
    實(shí)際編碼中,會(huì)存在返回圖片到客戶端的情況,如果也采用JSON格式傳輸?shù)脑?,需要把圖片轉(zhuǎn)成Base64格式的傳包裝,然后再傳輸?shù)娇蛻舳私馕觥?BR>    這里是一個(gè)演示,首先把圖片轉(zhuǎn)成流:
    Image1.Picture.Graphic.SaveToStream(ss);
    然后編碼成base64格式的:
    EncodeStream(ss, ss1);
    注意ss和ss1的定義:
    var
    ss: TMemoryStream;
    ss1,ss2 : TStringStream;
    EncodeStream的調(diào)用需要引用EncdDecd.pas單元。
    然后把流轉(zhuǎn)成字符串
    var
    sdata : string;
    begin
    ...
    sData := ss1.DataString;
    ...
    end;
    再把該字符串包裝到JSON串:
    var
    aqjson : TQJSON;
    begin
    aqjson := TQJSON.Create;
    aqjson.Parse(memo3.Lines.Text);
    ...
    aqjson.AddArray('pic').Add.AsString :=sdata;
    ...
    end;
    這樣圖片就打包到JSON里面了,傳到客戶端以后,再反過來解析即可:
    ss2 := TStringStream.Create(aqjson.ItemByName('pic').Items[0].value);
    DecodeStream(ss2,ss);//將base64字符流還原為內(nèi)存流
    ss.Position := 0; // 必須
    Image2.Picture.Graphic.LoadFromStream(ss);