Delphi字典保存/加载。 TDictionary不可序列化?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Delphi字典保存/加载。 TDictionary不可序列化?相关的知识,希望对你有一定的参考价值。
TDictionary:SaveToFile / LoadFromFile
多么优雅的解决方案!首先,一切都按预期运行。
内容以JSON格式保存到文件中,该格式看起来正确。但重新加载文件后,出现了一个问题:
Type
TEnumCategTypes = ( e_SQL1, e_VBA, e_Text );
TCategParams = class
fontStyles : TFontStyles;
rgbColor : COLORREF;
end;
TdictCategory = class ( TDictionary<TEnumCategTypes, TCategParams> )
public
public class function LoadFromFile( const AFileName: string ): TdictCategory;
public class procedure SaveToFile( const AFileName: string; dict: TdictCategory );
end;
implementation
class procedure TdictCategory.SaveToFile( const AFileName: string; dict: TdictCategory );
var
stream : TStringStream;
begin
try
stream := TStringStream.Create( TJson.ObjectToJsonString( dict ) ) ;
stream.SaveToFile( AFileName )
finally
stream.Free;
end;
end;
//---
class function TdictCategory.LoadFromFile( const AFileName: string ): TdictCategory;
var
stream: TStringStream;
begin
stream := TStringStream.Create;
try
stream.LoadFromFile( AFileName );
result := TJson.JsonToObject<TdictCategory>( stream.DataString );
finally
stream.Free;
end;
end;
测试如下。所有的荣耀都结束了。这是代码,包括评论:
..
var
cc: Colorref;
begin
.. // fill values
cc := DictCategory.Items[ e_SQL1 ].rgbColor; // Okay, it works
TdictCategory.SaveToFile( 'category.json', DictCategory ); // Even the contents of the file, looks good
DictCategory.Clear;
DictCategory.Free;
DictCategory := nil;
DictCategory := TdictCategory.LoadFromFile( 'category.json' ); // DictCategory is no longer NIL, and it looks optically well..
cc := DictCategory.Items[ e2_sql_aggregate ].rgbColor; // C R A S H !!! with AV
看来Delphi(柏林10.1),无法序列化词典!如果这是真的,那真的会伤害我。我相信还有很多其他人。或者附加代码中是否有任何错误?
TJson.JsonToObject
最终将使用其默认构造函数实例化对象(请参阅REST.JsonReflect.TJSONUnMarshal.ObjectInstance
)。
现在看看System.Generics.Collections
,你会发现TDictionary<TKey,TValue>
没有默认的构造函数(不,RTTI没有关于参数默认值的信息,因此不会考虑使用Capacity: Integer = 0
的构造函数)。
这意味着RTTI将进一步查找并找到TObject.Create
并在字典类上调用它将为您留下一半初始化对象(没有运行您的代码我猜它的FComparer
没有被分配TDictionary<TKey,TValue>
的构造函数会完成)。
长话短说:在你的TdictCategory
中添加一个无参数构造函数,然后在那里调用inherited Create;
。然后TJSONUnMarshal.ObjectInstance
将找到无参数构造函数并调用所有必需的代码以获得正确初始化的实例。
无论如何,你可能不会对结果感到满意,因为REST.JsonReflect
只是序列化实例的所有内部状态(除非通过RTL类中没有完成的属性明确排除),因此也反序列化它们,这意味着这样的JSON只是Delphi -to-Delphi兼容。
以上是关于Delphi字典保存/加载。 TDictionary不可序列化?的主要内容,如果未能解决你的问题,请参考以下文章
无需借助 csv 文件即可保存和加载复杂的 python 字典