zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    算法手记 之 数据结构(并查集详解)(POJ1703)
    ACM/ICPC 之 数据结构-线段树思想(POJ2182,含O(n^2)插入式解法)
    算法手记 之 数据结构(线段树详解)(POJ 3468)
    ACM/ICPC 之 快排+归并排序-记录顺序对(TSH OJ-LightHouse(灯塔))
    题目1113:二叉树 (计算某个结点的子结点个数)
    题目1078:二叉树遍历 (已知先序遍历和中序遍历,求后序遍历+未解决)
    题目1107:搬水果(哈夫曼树+快速排序+冒泡排序)
    题目1433:FatMouse (未解决)
    BootStrap入门教程 (四) :JQuery类库插件(模态窗口,滚动监控,标签效果,提示效果,“泡芙”效果,警告区域,折叠效果,旋转木马,输入提示)
    BootStrap入门教程 (三) :可重用组件(按钮,导航,标签,徽章,排版,缩略图,提醒,进度条,杂项)
  • 原文地址:https://www.cnblogs.com/findumars/p/6729216.html
Copyright © 2011-2022 走看看