DELPHI XE2 采用 JSON 的方式来序列化对象

DELPHI XE2 采用 JSON 的方式来序列化对象

以下代码测试通过。问题是里面的中文,在反序列化后是乱码。 


1. 序列化对象为字符串,Subject 里面的中文看起来正常,仍然是中文;

2. 反序列化为对象后,Subject 里面的中文是乱码。


XE2 处理 Unicode 还是有问题啊。


TItemRecord = class

  private

     FID: string;

     FSubject: string;

     FADate: TDateTime;

  published

    property ID: string read FID write FID;

    property Subject: string read FSubject write FSubject;

    property ADate: TDateTime read FADate write FADate;

  end;



procedure TForm1.Button3Click(Sender: TObject);
var
JO:  TJSONObject;
P:TJSONPair;
A:TJSONArray;
B:TBytes;
S:string;
JM:TJSONMarshal;
JUM:TJSONUnMarshal;
Item:  TItemRecord;
V, V2:TJSONValue;

UJ: TJSONUnMarshal;
begin
//采用 JSON
JM:=TJSONMarshal.Create;

Item := TItemRecord.Create;

with ClientDataSet1 do
begin
Item.ID :=  FieldByName('ID').AsString;
Item.Subject :=  FieldByName('Subject').AsString;
Item.ADate :=  FieldByName('ADate').AsDateTime;
end;

V:=JM.Marshal(Item);  //序列化
S := V.ToString;

Item.Free;
V.Free;

Memo1.Lines.Text := S;


//------------------- 反序列化-------------
JO :=  TJSONObject.Create;
JO.Parse(BytesOf(S), 0, Length(S));  //将字符串变回 Json  对象


UJ := TJSONUnMarshal.Create;
Item := UJ.Unmarshal(JO) as  TItemRecord;  //将 Json 对象变回我自己的对象。


Memo1.Lines.Add('-----------');

Memo1.Lines.Add('ID = ' + Item.ID);
Memo1.Lines.Add('Subject = ' +  Item.Subject);   //问题: 对字符串里面的汉字编码没搞好,有问题。
Memo1.Lines.Add('Date = ' +  DateTimeToStr(Item.ADate));
end;


---------------------------------------------------- 分隔符 -------------------------


前面说到,把对象用 ToString 的方法输出为字符串时,对象里面的中文在字符串里面是正确的,把字符串写道 TMEMO 里面显示出来的中文正常。但如果这时候把这个字符串用 JO.Parse(BytesOf(S), 0, Length(S)); 语句变回对象,则对象的中文字段值是乱码。


采用:B := TEncoding.ASCII.GetBytes(S); 的方式获得的 TBytes 用于 Parse,出来的对象,中文值也是乱码;

如果采用 B := TEncoding.Unicode.GetBytes(S); 的方式获得的 TBytes 用于Parse无法获得正确的对象,即运行 Jo.Parse(B, 0); 时会出现异常。


测试,不输出字符串,而是直接输出 TBytes,然后再拿这个 TBytes 去 Parse,获得的对象,中文字段值OK,没有乱码。


SetLength(B, 200);

  i := V.ToBytes(B, 0);

JO := TJSONObject.Create;

Jo.Parse(B, 0);

UJ := TJSONUnMarshal.Create;

Item := UJ.Unmarshal(JO) as TItemRecord;


这样获得的 Item 对象,其中文字段值没乱码。


也就是说,它的 ToString 输出的不知道是什么编码,需要按其编码变换回 TBytes 才行。简单的 BytesOf(S) 不行。


----------------------------

继续测试:采用  UTF8 字符串

S := V.ToString;
S8 :=  Utf8Encode(S);  //S8: UTF8STRING;

V2  := TJSONObject.ParseJSONValue(S8);  //V2: TJSONValue;

然后,  Item := UJ.Unmarshal(V2) as TItemRecord; 可以成功获得有中文字段值的对象!

也就是说,DELPHI  自带的 JSON 库,不能正确处理 UNICODE 双字节字符串,但能处理 UTF8 字符串。


-------------------------

继续:要处理中文,上面采用 Jo.Parse(B, 0); 的方式,直接处理中文字符串,获得的对象的中文字段值会乱码。


这样处理就对了:


V: TJSONValue;


V := TJSONObject.ParseJSONValue(S);

UJ := TJSONUnMarshal.Create;

Item := UJ.Unmarshal(V) as TItemRecord; 


这样获得的对象,字段的中文值不是乱码,正常了。


总结:不要用 TJSONObject 的对象的 Parse 方法来解析字符串为 JSON 对象,而应该用类方法 TJSONObject.ParseJSONValue(S) 的方式来获得 TJSONValue 对象,然后拿这个 JSONValue 对象去反序列化出来的对象,中文没问题。


---------------------------------

总结:绕了一大圈,其实很简单!它是可以直接处理UNICODE字符串的。只是 DELPHI 给出的这个JSON库里面的对象的方法,不太直观。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值