3

我正在使用 Delphi Xe5,并且我有一个组件,它基本上使用 IDTCPCLient(套接字)与服务器通信并以 JSON 的形式检索数据。我已经为您省去了所有的连接代码等。它可以工作。返回的 JSON 也可以工作。我遇到的麻烦是将我的 JSON 转换为 StringList,然后我用它来将值列表写入列表框并将其余 JSON 数据对象存储在 TSTrings OBjects 属性中。

我有很多有趣的事情发生。

1.) 我一辈子都无法让 List 属性正常工作。我使用这个列表来存储我的 JSON。一个字符串值,然后是列表中每个项目的整个对象。你会注意到在 JSONToStringList 方法中,我清除了字符串列表(它被注释掉了,因为当它不是时,我的程序挂起)

2.) 对于需要的多个 JSON 集多次调用该方法后,我的列表中出现重复值

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;

我希望这一切都可以理解。如果您需要查看更多内容,请告诉我。请随时纠正您在我的代码中看到的任何错误。我一直在学习:) - 谢谢你的帮助

4

3 回答 3

1

事实证明,FList 属性不应该被发布,而是被公开。这使得由于列表仅在运行时填充和清空,而不是在设计时。

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

不知道为什么会这样,但它现在似乎工作得很好

调用 List.Clear 而不是 FList.Clear;

于 2013-11-08T16:31:56.580 回答
1
  1. 如果 FList.Clear 挂起,则很可能是内存损坏问题。我怀疑的前两件事是您没有调用构造函数,或者内存的一部分已被其他内容覆盖。

  2. 列表中的重复值是否是由于您注释掉了 FList.Clear 造成的。无论如何,我建议使用调试器来查看列表中的内容或记录添加到列表中/从列表中删除的所有内容。这应该让您了解列表中不需要的值的来源。

  3. 作为一般建议,您无需在释放对象之前检查对象是否不为零。无论如何,检查都是在 Free(或 FreeAndNil 的 Free 部分)中进行的。

于 2013-11-08T07:16:17.430 回答
0

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.

于 2013-12-14T10:57:02.447 回答