4

我有一个接受字符串参数“CompanyName”的服务器方法“CustomerLookup”,用户可以输入任何字符,CustomerLookup 方法将返回部分符合条件的客户列表。我的 REST URL 如下所示,最后一个词“t”是方法的参数

http://localhost/datasnap/rest/TSales_SM/CustomerLookup/t

我的预期结果是,如果用户输入“t”,方法将返回所有与“t”部分匹配的客户公司名称。但我发现某些字符,如 T & Y 将转换为 True,N & F 将转换为 false。转换代码在 delphi unit -> DataSnap.DSService 中实现

procedure TDSRESTService.BuildParamArray(const Params: TStringList; var ParamArray: TJSONArray);
  var
    I: Integer;
    S: String;
    LValue: Double;
  begin
    ParamArray := TJSONArray.Create;
    for I := 0 to Params.Count - 1 do
    begin
      S := Params[I];
      if (AnsiIndexText(S,TrueBoolStrs) > -1) then
         ParamArray.AddElement(TJSONTrue.Create)
      else if AnsiIndexText(S,FalseBoolStrs) > -1 then
         ParamArray.AddElement(TJSONFalse.Create)
      else if AnsiCompareStr(S,NULL) = 0 then
         ParamArray.AddElement(TJSONNull.Create)
      else
         if TDBXPlatform.TryJsonToFloat(S, LValue) then
           ParamArray.AddElement(TJSONNumber.Create(S))
         else
           ParamArray.AddElement(TJSONString.Create(S));
    end;
  end;

谁能告诉我如何防止系统将 T、F、Y、N 转换为真假

谢谢。

4

3 回答 3

3

我认为您的代码中必须有一些地方定义如下:

SetLength(TrueBoolStrs, 4);
TrueBoolStrs[0] := 'True';
TrueBoolStrs[1] := 'T';
TrueBoolStrs[2] := 'Yes';
TrueBoolStrs[3] := 'Y';

SetLength(FalseBoolStrs, 4);
FalseBoolStrs[0] := 'False';
FalseBoolStrs[1] := 'F';
FalseBoolStrs[2] := 'No';
FalseBoolStrs[3] := 'N';

解决方法是将 TDSRestService.BuildParamArray 修补为:

procedure TDSRESTService.BuildParamArrayPatch(const Params: TStringList;
  var ParamArray: TJSONArray);
const NULL = 'null';
var
  I: Integer;
  S: String;
  LValue: Double;
begin
  ParamArray := TJSONArray.Create;
  for I := 0 to Params.Count - 1 do
  begin
    S := Params[I];
    if SameText(S, 'true') then
      ParamArray.AddElement(TJSONTrue.Create)
    else if SameText(S, 'false') then
      ParamArray.AddElement(TJSONFalse.Create)
    else if AnsiCompareStr(S, NULL) = 0 then
      ParamArray.AddElement(TJSONNull.Create)
    else if TDBXPlatform.TryJsonToFloat(S, LValue) then
      ParamArray.AddElement(TJSONNumber.Create(S))
    else
      ParamArray.AddElement(TJSONString.Create(S));
  end;
end;
于 2012-09-14T08:13:31.117 回答
2

他们正在转换为真和假,因为显示的代码正是这样做的。它调用AnsiIndexText(S,TrueBoolStrs),并且由于TrueBoolStrs数组包含 string T,它匹配并将一个TJSONTrue对象插入到您的数组中。如果您不希望这种情况发生,则必须避免调用此函数。

您可以执行更有限的搜索——而不是检查TrueBoolStrs数组中的所有值,只需检查您希望被视为布尔值的特定值。TrueBoolStrs您可以通过预先修改的内容来执行此操作而无需修改功能。(它是 SysUtils 单元中的全局变量。)但是,如果有人尝试使用包含数字的公司名称搜索客户,您会发现您会遇到类似的问题——它将参数转换为TJSONNumber.

你是编写程序和定义参数的人,所以如果你知道某个字段名称应该具有某种类型,那么当它可能猜错时,不要使用尝试猜测类型的函数。你已经知道CustomerLookup函数的参数是一个字符串,所以直接将参数转换为a TJSONString,或者直接使用原始字符串,没有任何JSON内容。

如果 Datasnap 完全在您的控制之外调用此函数,那么您可能会尝试找到一种方法来访问原始参数列表而不是 JSON 转换的参数列表,因为后者是不可靠的。

如果您想要 JSON 转换的版本,但您仍然可以访问原始参数列表,那么另一个想法是在基于上面显示的自定义编写的转换函数中包含某种形式的预期类型信息。然后该函数可以使用预期的类型来指导它的猜测——如果它正在读取一个应该具有布尔值的参数,则只搜索布尔字符串。

于 2012-09-13T13:33:10.843 回答
1

我有一个类似的问题,在这里可能是一样的。在我的 Servermethod 中,我期望有几个参数,我都以字符串的形式读入:

TServerMethods1.InsertMember(userid, Pw, MemberName, PhoneNumber: string): TJsonArray;

过了一会儿,人们抱怨电话号码转移不正确,前面的“0”被切断了。所以在过程中的某个地方,它会尝试将参数评估为它认为适合的类型!因此,对于电话号码“08979”,它认为它是一个数字,而我的 InsertMember 函数接收到一个“8979”作为电话号码。我可以想象它在你的情况下也是如此!解决方案是,不使用字符串类型,而是使用参数中的 JSonType。于是我把界面改成了:

TServerMethods1.InsertMember(juserid, jPw, jMemberName, jPhoneNumber: TJSONString): TJsonArray;

但是现在参数是 jsonobjects 并且需要特殊处理以防有人将参数留空。为此,我使用了局部变量。对于每个接收到的参数,我进行了以下检查并将其复制到局部变量:

如果未分配(jPhoneNumber)则 PhoneNumber:= '' else PhoneNumber:= UpperCase(StringReplace(jPhoneNumber.ToString,'"','',[rfReplaceAll]));

在那之后,一切都奏效了。在您的情况下,我认为他将 t 和 f 转换为布尔值,因为他试图从电话号码中提取一个数字!从那时起,我一直使用 TJSonobjects。

于 2013-06-18T05:03:35.577 回答