【问题标题】:Can I serialize an interface(_recordset) with TJSONMarshal?我可以用 TJSONMarshal 序列化接口(_recordset)吗?
【发布时间】:2013-06-20 18:43:12
【问题描述】:

我正在尝试使用 TJSONMarshal (XE4) 序列化对象,但是当对象具有像 _recordset 这样的接口属性时我遇到了问题

例如

我的班级:

  TFoo = class
  private
    FrsFoo: _recordset;
    FFooProp: integer;
  published
    property rsFoo: _recordset read FrsFoo write FrsFoo;
    property FooProp: integer read FFooProp write FFooProp;
  end;

我的功能:

function TestSerialize: string;
var
  JsonMarshal: TJSONMarshal;
  Foo: TFoo;
begin
  JsonMarshal := TJSONMarshal.Create(TJSONConverter.Create);
  Foo := TFoo.Create;
  Result := JsonMarshal.Marshal(Foo).ToString;
end;

结果:

{"type":"uTest.TFoo","id":1,"fields":{"FFooProp":0}}

rsFoo 没有序列化!

我可以序列化它吗?还是 TJSONMarshal 的限制?

【问题讨论】:

  • 接口不能轻易序列化,因为它们没有实现,它们只是接口。您希望序列化如何工作?您可能需要实现以支持另一个提供序列化服务的接口。
  • 是的,你是对的!但我有一个使用 rtti 将对象序列化为 XML 的实现,当“_recordset”出现时,我将其保存到流(TStringStream)中,这就是我如何将其“序列化”的方式。我认为也许我可以用 TJSONMarshal 做类似的事情,但“TJSONMarshal.RegisterConverter”只接受 TClass

标签: json delphi serialization recordset delphi-xe4


【解决方案1】:

就我而言,我只想序列化 _recordsets,所以我的解决方案是:

1) 获取所有_Recordset类型字段:

function Test.GetRecordsetFieldsFromObject(
  AObject: TObject): TStringList;
var
  Obj: TRttiType;
  Rtti: TRTTIContext;
  ObjField: TRttiField;
  IntfObj: IInterface;
  rsOut: _recordset;
begin
  Result := TStringList.Create;
  Obj := Rtti.GetType(AObject.ClassType);
  for ObjField in Obj.GetFields do
    if ObjField.FieldType.TypeKind = tkInterface then
    begin
      IntfObj := ObjField.GetValue(AObject).AsInterface;
      if IntfObj.QueryInterface(_Recordset, rsOut) = 0 then
      begin
        Result.Add(ObjField.Name);
        rsOut := nil;
      end;
    end;
end;

2) 为创建的每个字段注册转换器和还原器

  for FieldName in FieldNameList do
  begin
    JsonMarshal.RegisterConverter(TFoo, FieldName, function(Data: TObject; Field: String): TListOfStrings
    var
      Obj: TRttiType;
      ObjField: TRttiField;
      rsProp: _Recordset;
      strStream: TStringStream;
    begin
      SetLength(Result, 1);
      strStream := TStringStream.Create;
      try
        Obj := Rtti.GetType(data.ClassType);
        ObjField := Obj.GetField(Field);
        rsProp := ObjField.GetValue(Data).AsInterface as _Recordset;
        rsProp.Save(TStreamAdapter.Create(strStream) as IUnknown, adPersistXML);
        Result[0] := strStream.DataString;
      finally
        rsProp := nil;
        strStream.Free;
      end;
    end);

    JsonUnMarshal.RegisterReverter(TFoo, FieldName, procedure(Data: TObject; Field: String; Args: TListOfStrings)
    var
      Obj: TRttiType;
      ObjField: TRttiField;
      rsProp: _Recordset;
      strStream: TStringStream;
    begin
      rsProp := coRecordset.Create;
      strStream := TStringStream.Create(Args[0]);
      try
        Obj := Rtti.GetType(data.ClassType);
        ObjField := Obj.GetField(Field);
        strStream.Position := 0;
        rsProp.Open(TStreamAdapter.Create(strStream) as IUnknown, EmptyParam, adOpenUnspecified, adLockUnspecified, 0);
        ObjField.SetValue(Data, TValue.From<_Recordset>(rsProp));
      finally
        rsProp := nil;
        strStream.Free;
      end;
    end);
  end;

【讨论】:

    猜你喜欢
    • 2011-03-21
    • 2012-07-31
    • 1970-01-01
    • 2018-06-21
    • 2015-11-21
    • 1970-01-01
    • 2011-12-25
    • 1970-01-01
    • 2021-08-15
    相关资源
    最近更新 更多