无法将SuperObject JSON反序列化为Object

时间:2013-07-26 11:41:01

标签: json delphi delphi-xe2 access-violation superobject

类型:

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对象解析成一个新对象在指定的位置失败。我做错了什么?
顺便说一下,我不确定是否必须在ctx.AsType之前执行 NewOb:= TObj.Create ,但在这种情况下没有区别。

1 个答案:

答案 0 :(得分: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;