需要Delphi指针变量

时间:2018-02-20 06:21:29

标签: json delphi delphi-xe5

我正在尝试创建一个可以动态地将JSON字段附加到主JSON对象的全局过程。

procedure TJSONAdapter.addField(Key, Field: String);
var
  i: Integer;
  strArr: TStringList;
  j: Integer;

  pJSONObj: ^TJSONObject;
begin
  strArr:= TStringList.Create;
  Split('.', Key, strArr);

  pJSONObj:= @STATICJSON;

  i:= 0;
  repeat
  begin
    if IsSimpleJsonValue(STATICJSON.GetValue(strArr[i])) then
    begin
      Exit;
    end;

    if STATICJSON.GetValue(strArr[i]) is TJSONObject then
    begin
      pJSONObj:= @(STATICJSON.GetValue(strArr[i]) as TJSONObject); -> error in this line
      if i + 1 = strArr.Count then
      begin

我将我的值存储在名为STATICJSON的JSON对象中,直到程序关闭,然后我将其保存到文件中。

我正在尝试在STATICJSON中的某处添加字段。例如;

{
  "colors" :
    {
      "id": "F00",
      "color": "red",
      "details" : [
        {
         "name_en": "Red",
        },
        {
         "name_de": "Rot"
        }
      ]
   },
   {
      "id": "0F0",
      "color": "green",
      "details" : [
        {
         "name_en": "Green",
        },
        {
         "name_de": "Grün"
        }
      ]
   }
 }

如果我想在code数组中的第一个对象的每个details中添加colors字段:

obj.addField('colors.0.details.X', 'code');

我的期望:

{
  "colors" :
    {
      "id": "F00",
      "color": "red",
      "details" : [
        {
         "name_en": "Red",
         "code": ""
        },
        {
         "name_de": "Rot",
         "code": ""
        }
      ]
   },
   {
      "id": "0F0",
      "color": "green",
      "details" : [
        {
         "name_en": "Green",
        },
        {
         "name_de": "Grün"
        }
      ]
   }
 }

所以我试图使用指针转到第一种颜色的details数组和addField

我正在使用:

STATICJSON:= STATICJSON.GetValue(strArr[i]) as TJSONObject;

并且效果很好,但STATICJSON内容已更改为:

"details" : [
            {
             "name_en": "Red",
             "code": ""
            },
            {
             "name_de": "Rot",
             "code": ""
            }
          ]

所以我丢失了所有其他JSON内容。这就是我想使用指针的原因。但是我在这一行上收到了错误:

pJSONObj:= @(STATICJSON.GetValue(strArr[i]) as TJSONObject);
  

需要变量

更新:

procedure TJSONAdapter.addField(Key, Field: String);
var
  i: Integer;
  strArr: TStringList;
  j: Integer;

begin

  strArr:= TStringList.Create;
  Split('.', Key, strArr);

  i:= 0;
  repeat
  begin
    if IsSimpleJsonValue(STATICJSON.GetValue(strArr[i])) then
    begin
      Exit;
    end;

    if STATICJSON.GetValue(strArr[i]) is TJSONObject then
    begin
      STATICJSON:= STATICJSON.GetValue(strArr[i]) as TJSONObject;
      if i + 1 = strArr.Count then
      begin
        STATICJSON.AddPair(TJSONPair.Create(Field, ''));
        Exit;
      end;
    end;

    if STATICJSON.GetValue(strArr[i]) is TJSONArray then
    begin
      if strArr[i + 1] = 'X' then
      begin
        for j := 0 to (STATICJSON.GetValue(strArr[i]) as TJSONArray).Size -1 do
        begin
          ((STATICJSON.GetValue(strArr[i]) as TJSONArray).Get(j) as TJSONObject).AddPair(TJSONPair.Create(Field, ''));
        end;
        Exit;
      end;

      STATICJSON:= (STATICJSON.GetValue(strArr[i]) as TJSONArray).Get(StrToInt(strArr[i+1])) as TJSONObject;
      i:= i+1;

    end;
    Inc(i);
  end;
  until i = strArr.Count;

  strArr.Free;
end;

它有效,但由于这些原因:

STATICJSON:= STATICJSON.GetValue(strArr[i]) as TJSONObject;

STATICJSON:= (STATICJSON.GetValue(strArr[i]) as TJSONArray).Get(StrToInt(strArr[i+1])) as TJSONObject;

我丢失了主要的JSON内容,因此我不想分配STATICJSON,我只想将其地址分配给指针,以免丢失其内容。

1 个答案:

答案 0 :(得分:1)

Delphi对象是引用类型。 TJSONObject已经是指针,因此无需使用^TJSONObject

尝试更像这样的事情:

var
  STATICJSON: TJSONObject = nil;

procedure TJSONAdapter.addField(Key, Field: String);
var
  I, J, Index: Integer;
  strArr: TStringList;
  pJSONVal: TJSONValue;
begin
  strArr := TStringList.Create;
  try
    Split('.', Key, strArr);
    if STATICJSON = nil then begin
      STATICJSON := TJSONObject.Create;
    end;
    pJSONVal := STATICJSON;
    For I := 0 to strArr.Count-1 then
    begin
      if TryStrToInt(strArr[I], Index) then
      begin
        if not (pJSONVal is TJSONArray) then Exit; 
        pJSONVal := TJSONArray(pJSONVal).Get(Index);
      end
      else if strArr[I] = '*' then
      begin
        if I <> (strArr.Count-1) then Exit;
        if not (pJSONVal is TJSONArray) then Exit; 
        with TJSONArray(pJSONVal) do
        begin
          For J := 0 to Count-1 do
          begin
            pJSONVal := Get(Index);
            if pJSONVal is TJSONObject then
              TJSONObject(pJSONVal).AddPair(Field, '');
          end;
        end;
      end
      else if pJSONVal is TJSONObject then
      begin
        pJSONVal := TJSONObject(pJSONVal).Get(strArr[I]);
        if pJSONVal = nil then Exit;
      end
      else Exit;
    end;
    if pJSONVal is TJSONObject then
      TJSONObject(pJSONVal).AddPair(Field, '');
  finally
    strArr.Free;
  end; 
end;

obj.addField('colors.0.details.*', 'code');