3

DXE2でSuperObjectを使用してjsonからインターフェイスフィールドを含むオブジェクトを逆シリアル化するのに問題があります(シリアル化は正常に機能します)。次のことを考慮してください。

  ITest = interface(IInterface)
    ['{9E5623FF-1BC9-4FFA-919D-80C45EE24F38}']
    function GetField3() : string;
    procedure SetField3(Value: string);
    property FField3: string read GetField3 write SetField3;
  end;

  TTest = class(TInterfacedObject, ITest)
  private
    FField3: string;
    function GetField3() : string;
    procedure SetField3(Value: string);
  public
    property Field3: string read GetField3 write SetField3;
    constructor Create(Field3: string);
  end;

  TMyClass = class(TObject)
  public
    FField1: string;
    FField2: string;
    FTest:  ITest;
    constructor Create(Field1: string; Field2: string; Test: ITest);
  end;

  // TTest-stuff omitted for brevity.

constructor TMyClass.Create(Field1, Field2: string; Test: ITest);
begin
  FField1 := Field1;
  FField2 := Field2;
  FTest := Test;
end;

var
  MyClass:        TMyClass;
  MyClass2:       TMyClass;
  JSONObj:        ISuperObject;
  SuperContext:   TSuperRttiContext;
begin
  MyClass := TMyClass.Create('Test1', 'Test2', TTest.Create('Test3'));
  SuperContext := TSuperRttiContext.Create();
  JSONObj := SuperContext.AsJson<TMyClass>(MyClass);
  WriteLn(JSONObj.AsString);
  MyClass2 := SuperContext.AsType<TMyClass>(JSONObj);
  MyClass2.Free();
  ReadLn;
end.

実行がフィールドのTSuperRttiContext.FromJson.FromClassチェックにFTest到達すると、doo-dooは天井のプロペラ(または、必要に応じてテーブルに取り付けられたもの)に当たります。この時点で、Result := FromJson(f.FieldType.Handle, GetFieldDefault(f, obj.AsObject[GetFieldName(f)]), v);が呼び出され、SuperObject.pasコードの興味深い部分に移動します。簡潔にするために、ここで複製します。

  procedure FromInterface;
  const soguid: TGuid = '{4B86A9E3-E094-4E5A-954A-69048B7B6327}';
  var
    o: ISuperObject;
  begin
    if CompareMem(@(GetTypeData(TypeInfo).Guid), @soguid, SizeOf(TGUID)) then
    begin
      if obj <> nil then
        TValue.Make(@obj, TypeInfo, Value) else
        begin
          o := TSuperObject.Create(stNull);
          TValue.Make(@o, TypeInfo, Value);
        end;
      Result := True;
    end else
      Result := False;
  end;

に割り当てられた値soguidはの値ISuperObjectであるため、明らかに2つは一致しません(テスト中ですITest、覚えていますか?)。だから私はこれをどうすればいいのか少し迷っています。1つ以上のインターフェイスフィールドで構成されるオブジェクトを逆シリアル化することは違法ですか?

これは非常に一般的な使用例のように思われるので、信じがたいです。選択する特定のインターフェースの実装を知ることは簡単ではないかもしれないという事実を理解することができます。それでも、前文のコメントから、インターフェイスされたオブジェクトがサポートされることになっていることがわかります-http://code.google.com/p/superobject/source/browse/trunk/superobject.pas#47

誰かがこれを解決したなら、きっと素晴らしいでしょう。ありがとう!:)

4

0 に答える 0