4 votes

L'URL RESTful de Delphi datasnap, si elle contient un paramètre avec le caractère T/F/Y/N, sera converti en booléen True et False.

J'ai une méthode serveur "CustomerLookup" qui accepte un paramètre de type chaîne de caractères "CompanyName". L'utilisateur peut saisir n'importe quel caractère et la méthode CustomerLookup renvoie une liste de clients qui correspondent partiellement aux critères. Mon URL REST ressemble à ce qui suit, le dernier mot "t" étant le paramètre de la méthode.

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

Le résultat attendu est que si l'utilisateur saisit "t", la méthode renverra le nom de la société de tous les clients qui correspondent partiellement à "t". Mais j'ai découvert que pour certains caractères comme T et Y seront convertis en Vrai, N et F seront convertis en faux. Le code de conversion est implémenté dans l'unité 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;

Quelqu'un peut-il me dire comment empêcher le système de convertir T, F, Y, N en vrai et faux ?

Gracias.

3voto

Chau Chee Yang Points 3515

Je pense qu'il doit y avoir quelque part dans votre code définir quelque chose comme :

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

Une solution de contournement consisterait à modifier TDSRestService.BuildParamArray en :

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;

2voto

Rob Kennedy Points 107381

Ils sont convertis en vrai et faux parce que le code montré fait exactement cela. Il appelle AnsiIndexText(S,TrueBoolStrs) et puisque le TrueBoolStrs contient la chaîne de caractères T il correspond et insère un TJSONTrue dans votre tableau. Si vous ne voulez pas que cela se produise, vous devrez éviter d'appeler cette fonction.

Vous pourriez effectuer une recherche plus limitée - au lieu de vérifier toutes les valeurs de la rubrique TrueBoolStrs il suffit de vérifier les valeurs spécifiques que vous voulez traiter comme des valeurs booléennes. Vous pourriez le faire sans modifier la fonction en modifiant le contenu de TrueBoolStrs à l'avance. (Il s'agit d'une variable globale dans l'unité SysUtils.) Cependant, vous constaterez que vous obtenez des problèmes similaires si quelqu'un essaie de rechercher des clients dont le nom de société contient un chiffre - il convertit l'argument en un TJSONNumber .

C'est vous qui écrivez le programme et définissez les paramètres, donc si vous savez qu'un certain nom de champ doit avoir un certain type, alors n'utilisez pas une fonction qui essaie la fonction devinez le type quand il pourrait se tromper. Vous savez déjà que le paramètre de la méthode CustomerLookup est une chaîne de caractères, il suffit donc de convertir le paramètre en un mot de passe. TJSONString directement, ou simplement utiliser la chaîne originale sans aucun élément JSON.

Si Datasnap appelle cette fonction en dehors de votre contrôle, vous pouvez essayer de trouver un moyen d'accéder à la liste de paramètres originale au lieu de la liste convertie en JSON, car cette dernière n'est pas fiable.

Si vous voulez la version convertie en JSON, mais que vous avez toujours accès à la liste de paramètres d'origine, une autre idée serait d'inclure une forme d'information sur le type attendu dans une fonction de conversion personnalisée basée sur celle présentée ci-dessus. La fonction peut alors utiliser le type attendu pour guider sa recherche, en ne recherchant les chaînes booléennes que si elle lit un paramètre qui est censé avoir une valeur booléenne.

1voto

Niels Points 33

J'ai eu un problème similaire qui pourrait être le même ici. Dans mon Servermethod, j'attendais plusieurs paramètres que j'ai tous lus comme des chaînes de caractères :

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

Après un certain temps, les gens se sont plaints que le numéro de téléphone n'était pas transféré correctement et que le premier '0' était coupé. Donc, quelque part dans le processus, il essaie d'évaluer le paramètre à un type qu'il pense convenir ! Ainsi, pour le numéro de téléphone '08979', il pense qu'il s'agit d'un numéro et ma fonction InsertMember a reçu un '8979' comme numéro de téléphone. Je peux imaginer qu'il a fait la même chose dans votre cas ! La solution était de ne pas utiliser le type string mais le JSonType dans le paramètre. J'ai donc changé l'interface en :

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

Mais maintenant les paramètres sont des jsonobjects et nécessitaient un traitement spécial au cas où quelqu'un laissait un paramètre vide. Pour cela, j'ai utilisé des variables locales. Pour chaque paramètre reçu, je faisais la vérification suivante et la copiait dans une variable locale :

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

Après cela, tout a fonctionné. Dans votre cas, je pense qu'il a converti t et f en valeur booléenne car il a essayé de faire un numéro à partir du numéro de téléphone ! Depuis, j'utilise toujours TJSonobjects.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X