Delphi JSONArray SetJSONValue访问冲突

时间:2015-11-11 12:18:39

标签: arrays json rest delphi datasnap

我有一个JSONArray作为参数传递给我的服务器。我有一个由&#34生成的方法生成datasnap客户端类"程序以及何时到达第一个" SetJsonValue"它给我一个访问冲突,这个错误来来往往没有明显的原因。我在局域网中使用了Rest服务器(也使用了http,但尚未使用它进行测试)。有时它会通过重新启动我的计算机/编译器来解决,但有时会持续更长时间。

该方法如下:

if FExecutaInsertCommand = nil then
begin
  FExecutaInsertCommand := FConnection.CreateCommand;
  FExecutaInsertCommand.RequestType := 'POST';
  FExecutaInsertCommand.Text := 'TServerMethods."ExecutaInsert"';
  FExecutaInsertCommand.Prepare(TServerMethods_ExecutaInsert);
end;
FExecutaInsertCommand.Parameters[0].Value.SetWideString(database);
FExecutaInsertCommand.Parameters[1].Value.SetWideString(Tabela);
FExecutaInsertCommand.Parameters[2].Value.SetJSONValue(aValores,   FInstanceOwner);
FExecutaInsertCommand.Parameters[3].Value.SetJSONValue(aTipos,   FInstanceOwner);
FExecutaInsertCommand.Parameters[4].Value.SetInt32(usuario);
FExecutaInsertCommand.Execute(ARequestFilter);
Result := FExecutaInsertCommand.Parameters[5].Value.GetInt32;

从这里调用该方法:

result := DMClient.ServerMethodsClient.ExecutaInsert(banco, Tabela, GeraJSONArray(Registro), GeraJSONArray(GetStrings(Registro.DataType)), CodigoUsuarioLogado);

并且JSONArrays生成如下:

function GeraJSONArray(Valores: TVariantArray) : TJSONArray;
var
  i : Integer;
begin
  result := TJSONArray.Create;
  for i := 0 to Length(Valores.Values) - 1 do
    result.Adiciona(Valores.Values[i], Valores.DataType[i]);
end;

function GeraJSONArray(Valores: TArray<String>) : TJSONArray;
var
  i : Integer;
begin
  result := TJSONArray.Create;
  for i := 0 to Length(Valores) - 1 do
    result.AddElement(TJSONString.Create(Valores[i]));
end;

JsonArray.Adiciona:

procedure TJSONArrayHelper.Adiciona(valor: variant; DataType: TFieldType);
var
  JSONValue : TJSONValue;
begin
  if not (VarIsEmpty(valor)) and not (VarIsNull(valor)) then
  begin
    case DataType of 
      TFieldType.ftString,
      TFieldType.ftMemo,
      TFieldType.ftFmtMemo,
      TFieldType.ftFixedChar,
      TFieldType.ftWideString : JSONValue := TJSONString.Create(valor);
      //-----------------------------------------------//
      TFieldType.ftSmallint,
      TFieldType.ftInteger,
      TFieldType.ftWord,
      TFieldType.ftFloat,
      TFieldType.ftCurrency,
      TFieldType.ftAutoInc,
      TFieldType.ftLargeint,
      TFieldType.ftSingle,
      TFieldType.ftBCD : JSONValue := TJSONNumber.Create(valor);
      //-----------------------------------------------//
      TFieldType.ftDateTime : JSONValue :=     TJSONString.Create(DateTimeParaString(valor));
    end;
  end
  else
  begin
    JSONValue := TJSONNull.Create;
  end;
  if JSONValue <> nil then
    AddElement(JSONValue);
end;

参数2生成错误,但参数3不生成,我认为有关Adiciona程序的问题

1 个答案:

答案 0 :(得分:1)

Adiciona方法中,如果DataType不是case语句中列出的任何值,则您的本地JSONValue变量仍然未初始化。特别要注意的是,变量的默认值是不是 nil - 没有本地对象引用变量将具有的默认值 - 所以在方法结束时检查{{1这是一个无意义的比较。

documentation lists 52 possible TFieldType values;您的代码只处理15.您可以使用JSONValue <> nil子句来说明剩下的内容:

else

编译器应该警告您该变量可能未被初始化,尽管该警告所需的分析不可能是完美的,因此编译器可能无法检测到该情况。如果编译器警告您并且您忽略了警告,那么请将此作为教训。

我们可能期望将未初始化的对象引用添加到数组中,这与您观察到的访问冲突异常一致。析构函数将从数组中获取未初始化的值,并尝试在其上调用case DataType of ... else raise Exception.CreateFmt('Unexpected field type (%d)', [Ord(DataType)]); 。在非对象引用的事物上调用方法可能会导致许多问题;您可以希望的最佳事物就是您现在所看到的,这是一个例外,可以立即告诉您出现问题。 (想想如果程序默默地继续运行会有多糟糕。如果析构函数的GetOwned调用已经运行并且实际上破坏了程序中的其他内容,谁知道会遇到什么奇怪的问题?)