具有匿名JSON值的TJSONObject提供Exception EListError

时间:2015-05-01 15:01:21

标签: json delphi parsing

我正在解析并在Delphi XE8中抛出一个JSON结构,由于JSON结构,它给了我一个错误。如果我使用REST调试器,我可以看到网格中的数据,但如果我尝试手动获取它,我会收到错误。

这是JSON:

{
  "S":1,
  "U":"2898",
  "F":[],
  "D":[
    {
      "PRJCT_ID":"7",
      "PRJCT_NAME":"Hotel La Rosiere",
      "PRJCT_ADRESS":"le plateau"
    },  
    {
      "PRJCT_ID":"8",
      "PRJCT_NAME":"Hotel Delux",
      "PRJCT_ADRESS":"Centre Maison"
    },
    {
      "PRJCT_ID":"9",
      "PRJCT_NAME":"villedieu",
      "PRJCT_ADRESS":""
    }
  ]
}

我可以正确地从1级获得配对列表:S,F,D

但是如何测试数据是否是数据的匿名记录: 我试过了:

 if JSO.Pairs[i].JsonString.Value = '' then

我得到一个异常EListError消息......这是正常的,因为没有与值“{”PRJCT_ID“:”7“,”PRJCT_NAME“:”Hotel La Rosiere“,”PRJCT_ADRESS“:”le plateau“关联的JSON键“}”

我的代码是

procedure TAArray2.ExtractValues(JSO : TJsonObject);
var
  i : integer;
begin
  try
    i := 0;
    while (i < JSO.Count) do
    begin
      if JSO.Pairs[i].JsonValue is TJSONArray then   // array of values "Key":[{"Key":"Value","Key":"Value"},{"Key":"Value","Key":"Value"}]
      begin
        AddItem(JSO.Pairs[i].JsonString.Value, '', TJSonObject(JSO.Pairs[i].JsonValue)); // recursive call ExtractValues(TJSonObject(JSO.Pairs[i].JsonValue))
      end
      else if JSO.Pairs[i].JsonString.Value = '' then  // ERROR HERE : anonymous key : {"Key":"Value","Key":"Value"},{"Key":"Value","Key":"Value"} 
      begin
        AddItem(i, JSO.Pairs[i].JsonValue.Value);
      end
      else // standard creation : "Key":"Value"
      begin
        AddItem(JSO.Pairs[i].JsonString.Value, JSO.Pairs[i].JsonValue.Value);
      end;
      inc(i);
    end;
  finally

  end;
end;

我该怎么办?有人有个主意吗?

  

Nota:我调用匿名JSON记录设置JSON中没有的部分   我们可以说是数组“D”的成员:“D [1]”:{“PRJCT_ID”:“7”,   “PRJCT_NAME”:“Hotel La Rosiere”,“PRJCT_ADRESS”:“le plateau”}我将其称为anonymouse,因为此记录集没有自己的参考密钥。

这是完整的代码:关于构建TREE的词典 - 数据访问以及Key字符串值或索引:(注意我只会“解析”节点,如果需要(Get),如果不是,它将保持存储状态一个字符串)

unit Unit3;

interface

 uses
  Classes, System.SysUtils, System.Types, REST.Types, System.JSON, Data.Bind.Components,
  System.RegularExpressions, System.Variants,
  Generics.Collections;

type

  TAArray2 = class;

  PTRec=^TRec;

  TRec = class
  public
    Key : Variant;
    isRequired : boolean;
    Value : Variant;
    OldValue : Variant;
    JSON : string;
    JSO : TJSonObject;
    Items : TAArray2;
    procedure Add(Key : Variant ; Value: TRec);
  end;

   TAArray2 = class(TDictionary<Variant, TRec>)
   private
     function Get(Index: variant): TRec;
    procedure ExtractValues(JSO : TJsonObject);
   public
    procedure AddItem(Key: Variant; Value: Variant ; JSOnObject : TJSOnObject = nil);
    procedure ExtractFromJSON(JSonString: string ; RootElement : string = '');
     property Items[Cle : Variant]: TRec read Get; default;
   end;

implementation

procedure TRec.Add(Key : Variant ; Value: TRec);
begin
  if not(assigned(items)) then
    self.Items := TAArray2.Create;
  Items.Add( Key, Value);

end;

procedure TAArray2.AddItem(Key : Variant ; Value: Variant ; JSOnObject : TJSOnObject = nil);
var
  LocalRec : TRec;
begin

  LocalRec := Get(Key);

  if assigned(LocalRec) then
  begin

    LocalRec.Key := Key;
    LocalRec.Value := Value;
    LocalRec.JSO := JSOnObject;
  end
  else
  begin

   LocalRec := TRec.Create;
    LocalRec.Value := Value;
    LocalRec.Key := Key;
    LocalRec.JSO := JSOnObject;
    inherited Add( Key, LocalRec);

  end;

end;


function TAArray2.Get(Index: Variant): TRec;
var
  LocalRec : TRec;
begin

  if self.ContainsKey(Index) then
  begin
    LocalRec := inherited items[Index];
    if (LocalRec.JSON <> '') or (LocalRec.JSO <> nil) then
    begin
      LocalRec.Items := TAArray2.Create;

//      ExtractValues(JSO);
    end;

    Result := LocalRec;
  end
  else
  begin
    result := nil;

  end;

end;



// *****************************************************************************
//
// *****************************************************************************

procedure TAArray2.ExtractFromJSON(JSonString: string ; RootElement : string = '');
var
  JSO : TJsonObject;
  JSP : TJSonPair;
begin

  try
    JSO := TJSOnObject.ParseJSONValue(JSonString) as TJSONObject;

    try
      if (RootElement <> '') then
      begin
        JSP := JSO.Get(RootElement);
        if not(JSP.Null) then
        begin
          ExtractValues(TJSonObject(JSP.JsonValue));
        end;
      end
      else if Not(JSO.Null) then
      begin
        ExtractValues(JSO);
      end;

    finally
       JSO.Free();
    end;

  except
    on E:Exception do showmessage('Data Structure Error');
  end;
end;

我使用以下代码查看内容:

procedure TForm1.ShowAssocArray2(AAA : TAArray2 ; Level : integer);
var
  i : Integer;
  s : string;
  MyRec : TRec;
begin
  s := DupeString(' ',Level * 4);
  for MyRec in AAA.Values Do
  begin
    memo2.Lines.Add(s + string(MyRec.Key) + ' = ' + string(MyRec.Value) + ' (' + string(MyRec.JSON) + ')');  // Error Here
    AAA[MyRec.Key];
    if assigned(MyRec.Items) then
    begin
      if MyRec.Items.Count > 0 then
        ShowAssocArray2(MyRec.items, Level + 1);   // recursive for childrens
    end;
  end;
end;

procedure TForm1.Button5Click(Sender: TObject);
var
  MyList: TAArray2;
  MyRec, MyRec2 : TRec;
  i: Integer;
begin
  MyList := TAArray2.Create;
  MyList.ExtractFromJSON(Memo1.Lines.Text);

  ShowAssocArray2(MyList, 0);

end;

1 个答案:

答案 0 :(得分:1)

您没有正确访问阵列。当您找到TJSONArray时,您将其类型转换为TJSONObject,但数组不是对象。如果您使用as运算符进行类型转换,则会遇到运行时错误,但您没有。

你需要做更多这样的事情:

procedure TAArray2.ExtractValues(JSO : TJSONObject);
var
  i, j: integer;
  pair: TJSONPair;
  arr: TJSONArray;
  value: TJSONvalue;
begin
  for i := 0 to JSO.Count-1 do
  begin
    pair := JSO.Pairs[i];
    value := pair.JsonValue;
    if value is TJSONArray then
    begin
      arr := TJSONArray(value);
      for j := 0 to arr.Count-1 do
      begin
        value := arr[j];
        if value is TJSONObject then
        begin
          ExtractValues(TJSONObject(value));
        end
        else
        begin
          // value is not an object, do something else...
        end;
      end;
    end
    else
    begin
      AddItem(pair.JsonString.Value, value.Value);
    end;
  end;
end;

更新:JSON文档已经在树结构中。如果您尝试向用户显示该树,例如在TTreeView中,那么您可以使用以下内容:

function TAArray2.AddJSONValueToTreeView(const Name: String; Value: TJSONValue; ParentNode: TTreeNode = nil): TTreeNode;
var
  i: integer;
  obj: TJSONObject;
  pair: TJSONPair;
  arr: TJSONArray;
begin
  if ParentNode <> nil then
    Result := TreeView1.Items.AddChild(ParentNode, Name);
  else
    Result := TreeView1.Items.Add(nil, Name);
  if Value is TJSONObject then
  begin
    obj := TJSONObject(Value);
    for i := 0 to obj.Count-1 do
    begin
      pair := obj.Pairs[i];
      AddJSONValueToTreeView(pair.JsonString.Value, pair.JsonValue, Result);
    end;
  end
  else if Value is TJSONArray then
  begin
    arr := TJSONArray(Value);
    for i := 0 to arr.Count-1 do
    begin
      AddJSONValueToTreeView('['+IntToStr(i)+']', arr.Items[i], Result);
    end;
  end
  else
  begin
    TreeView1.Items.AddChild(Result, Value.Value);
  end;
end;