Delphi datasnap URL RESTful, if it contains a parameter with the symbol T / F / Y / N, converts True and False to a boolean value

I have a “CustomerLookup” server method that accepts the string parameter “CompanyName”, the user can enter any characters, and the CustomerLookup method returns a list of customers that partially meet the criteria. My REST URL is something like below, the last word "t" is a method parameter

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

My expected result: if the user enters "t", the method returns the company name of all customers, which partially matches "t". But I found that for a specific character, such as T and Y, it will be converted to True, N and F will be converted to false. The conversion code is implemented in the delphi block → 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 someone tell me how to prevent system conversion from T, F, Y, N to true and false

Thanks.

+4
source share
3 answers

I think your code should have 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 would be to patch TDSRestService.BuildParamArray for:

 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; 
+3
source

They are converted 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 the TJSONTrue object into your array. If you do not want this to happen, you will not need to call this function.

You can do a more limited search — instead of checking all the values ​​in the TrueBoolStrs array TrueBoolStrs just check which specific values ​​you want to process as booleans. You can do this without changing the function by first changing the contents of TrueBoolStrs . (This is a global variable in the SysUtils module.) However, you will find that you have similar problems if someone tries to find customers with a company name that contains a digit - it converts the argument to TJSONNumber .

It is you who write the program and determine the parameters, so if you know that a certain field name must have a certain type, then do not use a function that tries to guess the type if it can be mistaken. You already know that the parameter of the CustomerLookup function is a string, so just convert the parameter to TJSONString directly or just use the original string without any JSON stuff at all.

If Datasnap calls this function completely out of your control, you can try to find a way to access the list of source parameters instead of converted JSON, since the latter is unreliable.

If you want to convert the JSON version, but you still have access to the original list of parameters, then another idea would be to include some form of the expected type information in a custom conversion function based on the one shown above. Then the function can use the expected type to direct its guessing - only to search for boolean strings if it reads a parameter that should have a boolean value.

+2
source

I had a similar problem, which may be the same here. In my Servermethod, I was expecting several parameters that I all read as strings:

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

After some time, people complained that the phone number was not transmitted correctly, and the leading "0" was turned off. Therefore, somewhere in the process, he tries to evaluate the parameter to a type that he considers suitable! So for phonenumber '08979' he thinks it is a number, and my InsertMember function got the number 8979 as the phone number. I can imagine that in your case it was so! The solution was to not use the string type, but JSonType in parma. So I changed the interface to:

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

But now the parameter is jsonobjects and requires special processing if someone left the parameter empty. For this, I used local variables. For each parameter I received, I performed the following check and copied it into a local variable:

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

After that, everything worked. In your case, I think it converts t and f to a boolean, trying to make a number from a phone number! Since then I always use TJSonobjects.

+1
source

Source: https://habr.com/ru/post/1433980/


All Articles