2013-07-26 3 views
3

유형 :해제 직렬화 할 수 없습니다 객체로 객체 (superobject) JSON을

TData = record 
    str: string; 
    int: Integer; 
    boo: Boolean; 
    flt: Double; 
end; 

TDataArray = Array [0..5] of TData; 

TObj = class 
private 
    str: string; 
    int: Integer; 
    boo: Boolean; 
    flt: Double; 
public 
    constructor Create(s: string; i: Integer; b: Boolean; f: Double); 
end; 

Testcode 다음 (배열)와

procedure TFrmJSONRTTI.FormShow(Sender: TObject); 
var 
    DataArray, 
    NewArray : TDataArray; 
    Ob,NewOb : TObj; 
    so  : ISuperObject; 
    ctx  : TSuperRttiContext; 
    i  : integer; 
begin 
    Log('SERIALIZING Static data'); 
    Log(''); 
    Log('type'); 
    Log(' TData = record'); 
    Log(' str: string;'); 
    Log(' int: Integer;'); 
    Log(' boo: Boolean;'); 
    Log(' flt: Double;'); 
    Log(' end;'); 
    Log(''); 
    Log(' TDataArray = Array [0..5] of TData;'); 
    Log(''); 
    Log('var'); 
    Log(' DataArray: TDataArray;'); 
    for i := 0 to 5 do 
    begin 
    DataArray[i].str := 'str'+ inttostr(i); 
    DataArray[i].int := i; 
    DataArray[i].boo := (i > 3); 
    DataArray[i].flt := i; 
    end; 
    ctx := TSuperRttiContext.Create; 
    try 
    so := ctx.AsJson<TDataArray>(DataArray); 
    finally 
    ctx.Free; 
    end; 
    Log(''); 
    Log(so.AsJson); 
    Log(''); 
    Log('DE-SERIALIZING Static data'); 
    Log(''); 
    ctx := TSuperRttiContext.Create; 
    try 
    NewArray := ctx.AsType<TDataArray>(SO); 
    finally 
    ctx.Free; 
    end; 
    Log('New TDataArray:'); 
    for i := 0 to 5 do 
    begin 
    Log(' DataArray['+IntToStr(i)+'].str: ' + DataArray[i].str); 
    Log(' DataArray['+IntToStr(i)+'].int: ' + IntToStr(DataArray[i].int)); 
    Log(' DataArray['+IntToStr(i)+'].boo: ' + BoolToStr(DataArray[i].boo,true)); 
    Log(' DataArray['+IntToStr(i)+'].flt: ' + FloatToStr(DataArray[i].flt)); 
    end; 
    Log('------------------------------'); 
    Log(''); 
    Log('SERIALIZING Object'); 
    Log(''); 
    Log('TObj = class'); 
    Log('private'); 
    Log(' str: string;'); 
    Log(' int: Integer;'); 
    Log(' boo: Boolean;'); 
    Log(' flt: Double;'); 
    Log('public'); 
    Log(' constructor Create(s: string; i: Integer; b: Boolean; f: Double);'); 
    Log('end;'); 
    Log(''); 
    Ob := TObj.Create('test',5,true,1.2); 
    ctx := TSuperRttiContext.Create; 
    try 
    so := ctx.AsJson<TObj>(Ob); 
    finally 
    ctx.Free; 
    Ob.Free; 
    end; 
    Log(''); 
    Log(so.AsJson); 
    Log(''); 
    Log('DE-SERIALIZING Object'); 
    Log(''); 
    NewOb := TObj.Create('',0,false,0); 
    try 
    NewOb := ctx.AsType<TObj>(SO); // <== Exception $C0000005, AV at 0x0000000 read of addr 0x0000000 
    finally 
    ctx.Free; 
    end; 
    Log('New TObj:'); 
    with NewOb do 
    begin 
    Log(' str: ' + str); 
    Log(' int: ' + IntToStr(int)); 
    Log(' boo: ' + BoolToStr(boo,true)); 
    Log(' flt: ' + FloatToStr(flt)); 
    end; 
    NewOb.Free; 
end; 

첫 번째 부분 기록의 TObj와 두 번째 부분을 완벽하게 잘 작동 어디 JSON 개체를 새 개체로 구문 분석하려는 경우 지정된 위치에서 실패합니다. 내가 뭘 잘못하고 있니?
BTW 내가 해야할지 모르겠다면 NewOb : = TObj.Create 전에 ctx.AsType,하지만이 경우에는 아무런 차이가 없습니다.

답변

6

AV가 분명합니다. 널 포인터를 역 참조하고 있습니다. 여기 당신이 그것을 해제 한 후 ctx을 사용하고 있습니다.

ctx := TSuperRttiContext.Create; // CREATE ctx 
    try 
    so := ctx.AsJson<TObj>(Ob); 
    finally 
    ctx.Free;      // FREE ctx 
    Ob.Free; 
    end; 
    Log(''); 
    Log(so.AsJson); 
    Log(''); 
    Log('DE-SERIALIZING Object'); 
    Log(''); 
    NewOb := TObj.Create('',0,false,0); 
    try 
    NewOb := ctx.AsType<TObj>(SO); // USE ctx -- EXCEPTION 
    finally 
    ctx.Free; 
    end; 
+1

+1 좋은 캐치 : o) –

+0

오타 - 카피 파스타 오류. 감사! –

+2

@JanDoggen 코드 복사 및 붙여 넣기는 반복 된 섹션을 추출하여 하나의 방법으로 리팩토링해야하는 좋은 단서입니다. 다른 많은 이점 중에서도 이러한 종류의 오류는 방지됩니다. –