我正在尝试使用 TJSONMarshal (XE4) 序列化对象,但是当对象具有像 _recordset 这样的接口(interface)属性时我遇到了问题
例如
我的课:
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 的限制?
最佳答案
就我而言,我只想序列化 _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;
关于json - 我可以用 TJSONMarshal 序列化接口(interface)(_recordset)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17221370/