• 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库里面的对象的方法,不太直观。

     
    http://blog.sina.com.cn/s/blog_722bc92e0101hl88.html
  • 相关阅读:
    教材全解
    知乎、博客园等开放API接口
    学习正则表达式就这么简单
    C#操作域用户ADHelper
    跨线程时使用静态扩展方法更新控件
    C#中的WinForm的消息机制简述,及消息机制下Invoke,和BeginInvoke的使用和区别
    WinForm 捕获异常 Application.ThreadException + AppDomain.CurrentDomain.UnhandledException
    Winform异常处理之ThreadException、unhandledException及多线程异常处理
    深入理解C#中的IDisposable接口
    批处理应用的几个技巧
  • 原文地址:https://www.cnblogs.com/findumars/p/6729216.html
Copyright © 2020-2023  润新知