Delphi datasnap RESTful URL如果包含带字符T / F / Y / N的参数将转换为布尔值True和False

时间:2012-09-13 10:21:09

标签: delphi url rest delphi-xe2 datasnap

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

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

我的预期结果是,如果用户输入“t”,方法将返回部分匹配“t”的所有客户的公司名称。但我发现像T& Y将转换为True,N& F将转换为false。转换代码在delphi单元中实现 - > 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转换为真和假

感谢。

3 个答案:

答案 0 :(得分: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;

答案 1 :(得分:2)

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

您可以执行更有限的搜索 - 而不是检查TrueBoolStrs数组中的所有值,只需检查您希望将其视为布尔值的特定值。您可以在不修改函数的情况下通过提前修改TrueBoolStrs的内容来执行此操作。 (它是SysUtils单元中的全局变量。)但是,如果有人试图搜索公司名称包含数字的客户,您会发现类似的问题 - 它会将参数转换为TJSONNumber

您是编写程序并定义参数的人,因此如果您知道某个字段名称应该具有某种类型,那么请不要使用尝试 guess 的函数当它猜错时输入。您已经知道CustomerLookup函数的参数是一个字符串,所以只需将参数直接转换为TJSONString,或者只使用原始字符串而不需要任何JSON内容。

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

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

答案 2 :(得分:1)

我遇到了类似的问题。 在我的Servermethod中,我期待几个参数,我都读作字符串:

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

过了一段时间人们抱怨电话号码没有正确转移,领先的'0'被切断了。 所以在这个过程中,它试图将参数计算为它认为适合的类型!因此,对于电话号码'08979',它认为它是一个号码,我的InsertMember功能收到'8979'作为电话号码。我可以想象你的情况也一样! 解决方案是,不使用字符串类型,而是使用parmeter中的JSonType。 所以我将界面更改为:

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

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

如果没有Assigned(jPhoneNumber)那么       PhoneNumber:=''    其他       PhoneNumber:= UpperCase(StringReplace(jPhoneNumber.ToString,'“','',[rfReplaceAll]));

之后一切顺利。 在你的情况下,我认为他将t和f转换为布尔值,因为他试图从电话号码中取出一个数字! 从那时起,我总是使用TJSonobjects。