3

Types:

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;

First part with the (array of) record works perfectly fine, the second part with the TObj where I want to parse the JSON object into a new object fails at the indicated spot. What am I doing incorrectly?
BTW I'm not sure if I have to do the NewOb := TObj.Create before the ctx.AsType, but it makes no difference in this case.

1 Answer 1

6

The AV is clear - you're dereferencing a null pointer. Here you're using ctx after you have freed it.

  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;
Sign up to request clarification or add additional context in comments.

1 Comment

@JanDoggen Copying and pasting code is a good clue that you should extract the repeated sections and refactor it into a single method - among many other benefits, it prevents this kind of error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.