2017-12-15 23 views
1

TDictionarySaveToFileメソッド/LoadFromFileメソッドDelphiの辞書の保存/読み込み。 TDictionaryは直列化できませんか?

どのようなエレガントなソリューション! まず、すべてが期待どおりに実行されます。

コンテンツは、正しく見える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)、辞書をシリアル化することができないようです!それが本当なら、それは本当に私を傷つける。私は他にもたくさんあると信じています。または、添付されたコードにエラーがありますか?

+0

あなたの質問は非常に冗長です。これは 'TJson.JsonToObject (..)'(そしておそらく 'TJson.ObjectToJsonObject (..)')も 'TList 'や 'TDictionary 'のようなジェネリッククラスではうまく動作しません。 –

答えて

6

TJson.JsonToObject最終的にデフォルトコンストラクタ(REST.JsonReflect.TJSONUnMarshal.ObjectInstanceを参照)を使用してオブジェクトをインスタンス化します。

は今System.Generics.Collectionsに見て、あなたはTDictionary<TKey,TValue>は(Capacity: Integer = 0とコンストラクタは考慮されませんので、ノー、RTTIは、パラメータのデフォルト値に関する情報がありません)デフォルトコンストラクタを持っていないことがわかります。

これはRTTIはさらに見て、TObject.Createを見つけることを意味し、私は推測することなく、(半分の初期化されたオブジェクトを残すだろう辞書クラス上で実行したことを、あなたのコードを呼び出し、そのFComparerTDictionary<TKey,TValue>のコンストラクタを持っていることになる割り当てられていません完了)。

短い説明:パラメータのないコンストラクタをTdictCategoryに追加して、そこにinherited Create;と電話するだけです。その後、TJSONUnMarshal.ObjectInstanceはパラメータのないコンストラクタを見つけ、適切に初期化されたインスタンスを持つために必要なすべてのコードを呼び出します。

REST.JsonReflectは、(RTLクラスでは行われていない属性によって明示的に除外されていない限り)インスタンスの内部状態をすべてシリアライズするだけで、そのようにデシリアライズしますJSONはデルファイからデルファイにしか対応していません。

+1

合意された、デフォルトのコンストラクタがこのAVの理由かもしれません。単一のテストを実行することなく、私はちょうど 'FComparer'が(無効な参照として)シリアライズされ、デシリアライズされている可能性があると考えました。 Delphi RTLにいくつかの共通点がないことは間違いありません。クラスとフィールドの '[Serializable]'、 '[NonSerializable]属性を考えてみましょう。 – Victoria

+0

@StefanGlienke:TdictCategoryにパラメータ化されていないコンストラクタがテスト済みです。 テストはAVクラッシュなしで正しく行われました。 しかし、各PAIRについて、VALUEのすべての項目は空でした。最後のテストの前に、試行錯誤の方法に基づいて、 "TCategParams"の元の宣言を "TCategParams = class ** aFontStyles **:** Byte **; rgbColor:COLORREF; end;"に変更する必要があります。 SaveToFile部分のjsonテキストについて。 jsonファイルの内容が正しいようです –

関連する問題