Delphi 需要指针变量

Delphi pointer variable required

我正在尝试创建一个全局过程,它可以动态地将 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"
        }
      ]
   }
 }

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

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);

Variable required

更新:

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,只是想把它的地址赋给一个指针,这样内容就不会丢失了。

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');