Delphi datasnap RESTful URL if contain parameter with character T/F/Y/N will convert to boolean True and False

StackOverflow https://stackoverflow.com/questions/12404105

Question

I have a server method "CustomerLookup" that accept a string parameter "CompanyName", user may enter any characters and CustomerLookup method will return a list of customers that partially match the criteria. My REST URL is something like below, the final word "t" is the method's parameter

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

My expected outcome is if user enter "t", method will return all customers' companyname that partially match "t". But i found out for certain character like T & Y will convert to True, N & F will convert to false. The converting code is implemented in 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;

Can anyone tell me how to prevent system to convert of T, F, Y, N to true and false

Thanks.

Was it helpful?

Solution

I think there must be some where in your code define something like:

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

A workaround solution would be patch TDSRestService.BuildParamArray to:

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;

OTHER TIPS

They're converting to true and false because the code shown does exactly that. It calls AnsiIndexText(S,TrueBoolStrs), and since the TrueBoolStrs array contains the string T, it matches and inserts a TJSONTrue object into your array. If you don't want that to happen, you'll have to avoid calling this function.

You could perform a more limited search — instead of checking all the values in the TrueBoolStrs array, just check for the specific values you want to be treated as Boolean values. You could do this without modifying the function by modifying the contents of TrueBoolStrs in advance. (It's a global variable in the SysUtils unit.) However, you'll find that you get similar problems if someone tries to search for customers with a company name that contains a numeral — it converts the argument to a TJSONNumber.

You're the one writing the program and defining the parameters, so if you know that a certain field name should have a certain type, then don't use a function that tries the guess the type when it could guess wrongly. You already know that the parameter to the CustomerLookup function is a string, so just convert the parameter to a TJSONString directly, or just use the original string without any JSON stuff at all.

If Datasnap is calling this function entirely outside your control, then you might try to find a way to access the original parameter list instead of the JSON-converted one since the latter is unreliable.

If you want the JSON-converted version, but you still also have access to the original parameter list, then another idea would be to include some form of expected type information in a custom-written conversion function based on the one shown above. Then the function can use the expected type to guide its guessing — only searching for Boolean strings if it's reading a parameter that's supposed to have a Boolean value.

I had a similar problem which might be the same here. In my Servermethod I expected several parameter which I all read in as strings:

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

After a while people complained that the phone number is not transfered correctly and the leading '0' was cut off. So somewhere in the process it tries to evaluate the parameter to a type it thinks it suits! So for the phonenumber '08979' it thinks it is a number and my InsertMember function received a '8979' as phone number. I can imagine it did the same in your case! The solution was, to not use the string type but the JSonType in the parmeter. So I changed the interface to:

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

But now the parameter are jsonobjects and needed special handling in case somebody left a parameter blank. For this I used local variables. For every received parameter I did the following check and copied it to a local variable:

if not Assigned(jPhoneNumber) then PhoneNumber:= '' else PhoneNumber:= UpperCase(StringReplace(jPhoneNumber.ToString,'"','',[rfReplaceAll]));

After that it all worked. In your case I think he converts t and f to a boolean value as he tried to make a number out of the phone number! Since then I always use TJSonobjects.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top