I am trying to write a debugger visualizer for a TJSONObject or a TJSONValue. I have most of the visualizer working nicely. The problem I am having is getting a reference to the TJSONObject, or at least to the tostring() value of the TJSONObject.
According to the samples I've seen, as well as the nice post by Jeremy North at http://edn.embarcadero.com/article/40268, I should get what I need from the Show method of my IOTADebuggerVisualizerExternalViewer implementation. Specifically, from the Expression, TypeName, and EvalResult string parameters.
From what I understand, Expression is the name of variable being inspected (visualized), TypeName is the classname of the variable, and EvalResult is the default string representation of the variable.
For a simple test I placed a TMemo on my TFrame descendant. From the IOTADebuggerVisualizerExternalViewer.Show method I call the ShowJSONObject method of my TFrame, to which I pass Expression, TypeName, and EvalResult. The relevant code appears here:
function TDebuggerJSONVisualizer.Show(const Expression, TypeName, EvalResult: string;
SuggestedLeft, SuggestedTop: Integer):
IOTADebuggerVisualizerExternalViewerUpdater;
var
AForm: TCustomForm;
AFrame: TJSONViewerFrame;
VisDockForm: INTACustomDockableForm;
begin
VisDockForm := TJSONVisualizerForm.Create(Expression) as INTACustomDockableForm;
AForm := (BorlandIDEServices as INTAServices).CreateDockableForm(VisDockForm);
AForm.Left := SuggestedLeft;
AForm.Top := SuggestedTop;
(VisDockForm as IFrameFormHelper).SetForm(AForm);
AFrame := (VisDockForm as IFrameFormHelper).GetFrame as TJSONViewerFrame;
AFrame.ShowJSONObject(Expression, TypeName, EvalResult);
Result := AFrame as IOTADebuggerVisualizerExternalViewerUpdater;
end;
{ TStringListViewerFrame }
procedure TJSONViewerFrame.ShowJSONObject(const Expression, TypeName,
EvalResult: string);
begin
Memo1.Lines.Add(Expression);
Memo1.Lines.Add(TypeName);
Memo1.Lines.Add(EvalResult);
end;
As you can see, I at this point I am only trying to display the values of these three parameters from my ShowJSONObject method.
Here is a simple TJSONObject that I tried to display using the visualizer:
var
jo: TJSONObject;
begin
jo := TJSONObject.Create;
jo.AddPair('one', 'one');
jo.AddPair('two', TJSONNumber.Create(1)); //a breakpoint here
The result looks like this:
I was hoping that EvalResult would return the tostring representation of the TJSONObject, but it only returned the uninformative (), which is the same thing you see by default in the local variables window.
How do I get either the tostring representation of the TJSONObject for which the visualizer was invoked or a handle to the actual object, so I can deconstruct and display its value?
You need to evaluate your expression (including ToString call) using this procedure (just copied from my own visualizer source so it could use some local variables that are not declared here):
function TJSONViewerFrame.Evaluate(Expression: string): string;
var
CurProcess: IOTAProcess;
CurThread: IOTAThread;
ResultStr: array[0..4095] of Char;
CanModify: Boolean;
ResultAddr, ResultSize, ResultVal: LongWord;
EvalRes: TOTAEvaluateResult;
DebugSvcs: IOTADebuggerServices;
begin
begin
Result := '';
if Supports(BorlandIDEServices, IOTADebuggerServices, DebugSvcs) then
CurProcess := DebugSvcs.CurrentProcess;
if CurProcess <> nil then
begin
CurThread := CurProcess.CurrentThread;
if CurThread <> nil then
begin
EvalRes := CurThread.Evaluate(Expression, @ResultStr, Length(ResultStr),
CanModify, eseAll, '', ResultAddr, ResultSize, ResultVal, '', 0);
case EvalRes of
erOK: Result := ResultStr;
erDeferred:
begin
FCompleted := False;
FDeferredResult := '';
FDeferredError := False;
FNotifierIndex := CurThread.AddNotifier(Self);
while not FCompleted do
DebugSvcs.ProcessDebugEvents;
CurThread.RemoveNotifier(FNotifierIndex);
FNotifierIndex := -1;
if not FDeferredError then
begin
if FDeferredResult <> '' then
Result := FDeferredResult
else
Result := ResultStr;
end;
end;
erBusy:
begin
DebugSvcs.ProcessDebugEvents;
Result := Evaluate(Expression);
end;
end;
end;
end;
end;
end;
So now you can replace your Show function with something like this:
AFrame.ShowJSONObject(Expression, TypeName, Evaluate(Expression + '.ToString'));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With