3

类型:

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;

测试代码:

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;

带有(数组)记录的第一部分工作得很好,第二部分带有我想将 JSON 对象解析为新对象的 TObj 在指定的位置失败。我做错了什么?
顺便说一句,我不确定是否必须在 ctx.AsType 之前执行NewOb := TObj.Create,但在这种情况下没有区别。

4

1 回答 1

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;
于 2013-07-26T11:55:38.873 回答