LIVESTUFF
LIVESTUFF

Reputation: 137

JSON to StringList using Delphi Xe5

I am using Delphi Xe5 and I have a component that essentially uses IDTCPCLient (sockets) to talk with are server and retrieve data in the form of JSON. I have spared you all the connection code , etc. It works. The returned JSon works as well. The trouble I am having is converting my JSON into a StringList, which I then use to write out a list of values to a listbox and store the rest of the JSON data objects in the TSTrings OBjects property.

I have a number of funny things happen.

1.) I can't for the life of me get the List property to work properly. I use this list to store my JSON. A string value and then the entire object for each item in the list. You will notice that in the JSONToStringList method, I clear the stringlist (it is commented out, becuase when it isn't, my program hangs)

2.) I get dupplicate values in my list after calling the method more than once for multiple JSON sets needed

TConnector = class(TComponent)
  private
    { Private declarations }
    FList: TStrings; 
    procedure SetList(const Value: TStrings); 
  protected
    { Protected declarations }
  public
    { Public declarations }
    Constructor Create( AOwner : TComponent ); override;
    Destructor Destroy; Override;
    Procedure GenerateJSON;
    Procedure JSONToStringList(aJSonKey: String);
  published
    { Published declarations }
    property List: TStrings Read FList Write SetList; 

  end;


Constructor TConnector.Create(AOwner: TComponent);
begin
  inherited;
  FList:= TStringList.Create(True);
end;


destructor TConnector.Destroy;
begin
  if FList <> nil then
   FreeAndNil(FList);
  inherited;
end;

Procedure TConnector.GenerateJSON;
begin
if ResponseStream<>nil then
  Begin
  FreeAndNil(ResponseJSON_V);
  ResponseJSON_V := TJSONObject.ParseJSONValue(StreamToArray(ResponseStream),0) as TJSONValue;
  End;
end;

procedure TConnector.JSONToStringList(aJSonKey: String);
Var
  zLJsonValue  : TJSONValue;
  zLJSONArray: TJSONArray;
  zLJsonObject : TJSONObject;
  zI           : Integer;
begin
  if ResponseJSON_V is TJSONArray then
  begin
    zLJSONArray:= ResponseJSON_V as TJSONArray;
    zLJsonObject := zLJSONArray.Get(0) as TJSONObject;
  end
  else
  if ResponseJSON_V is TJSONObject then
  begin
    zLJSONArray:= nil;
    zLJsonObject := ResponseJSON_V as TJSONObject;
  end
  else
    Exit;
  if zLJSONArray<>nil then
  begin
     ***//FList.Clear;***
    for zLJsonValue in zLJSONArray do
    begin
      zLJsonObject := zLJsonValue as TJSONObject;
      for zI := 0 to zLJsonObject.Size-1 do
      begin
        if zLJsonObject.Get(zI).JsonString.Value = aJSonKey then
        begin
          FList.AddObject(zLJsonObject.Get(zI).JSONValue.Value, zLJsonObject);
        end;
      end;
    end;
  end
  else
  begin
    FList.Clear;
    for zI := 0 to zLJsonObject.Size-1 do
      begin
        if zLJsonObject.Get(zI).JsonString.Value = aJSonKey then
        FList.AddObject(zLJsonObject.Get(zI).JSONValue.Value, TJSONPair(zLJsonObject.Get(zI)));
      end;
  end;
end;

I hope this is all understandable. Please let me know if you need to see more. Please feel free to correct anything else you see bad in my code. I am always learning :) - thank you for your help

Upvotes: 3

Views: 4509

Answers (3)

user3065646
user3065646

Reputation: 1

your code cannot work ... U define a param called "aJSonKey" and u call it "ResponseJSON_V " into the procedure.

Moreover u call this "ResponseJSON_V" into GenerateJSON proc when there is no property called that way.

Upvotes: 0

LIVESTUFF
LIVESTUFF

Reputation: 137

It turns out , that the FList property should not have been published, but rather made public instead. Which makes since, cause the list is only filled and emptied at runtime, never at design time.

TLiveConnector = class(TComponent)
  private
    { Private declarations }
  protected
    { Protected declarations }
  public
    { Public declarations }
     List: TStrings;  
  published
  end;

Not sure exactly why that is the case, but it seem to work just fine now

Calling List.Clear instead of FList.Clear;

Upvotes: 1

Avo Murom&#228;gi
Avo Murom&#228;gi

Reputation: 1593

  1. If FList.Clear hangs then it's most likely memory corruption issue. First two thing I would suspect is that you have not called a constructor or that part of the memory has been overwritten by something else.

  2. Can the duplicate values in the list be cause by the fact that you commented out FList.Clear. Anyway, I suggest using a debugger to see what goes in to the list or log everything added to/removed from the list. This should give you the idea where unneeded values in the list are coming from.

  3. As a general advice you don't need to check if object is not nil before freeing it. The check is made in Free (or in the Free part of the FreeAndNil) anyway.

Upvotes: 1

Related Questions