Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

[REST/JSON] Pourquoi un Transtypage erreur


Sujet :

Delphi

  1. #1
    Membre extrêmement actif
    [REST/JSON] Pourquoi un Transtypage erreur
    Bonjour aux Delphistes

    J'essaie d'extraire les données d'une réponse REST avec Delphi 10.3.3.

    Je veux récupérer dans une variable string une valeur "JSONobject.value" qui est un string et j'obtiens une erreur "Transtypage de classe incorrect".

    J'avoue ne pas avoir la moindre expérience avec JSON...Ou est-ce que je me plante?

    J'ai comme réponse JSON en lisant le string "RESTResponse1.JSONText":


    [ { "header": "2;20200904 2;OUT;4;", "comment": null, "data": "21;1;074170382839;22;1;095008026503;", "status": -4, "statusmsg": "DOCS: doc_status is not valid" } ]
    Et mon code qui finit par l'erreur de transtypage est:


    RESTRequest1.Execute;
    objJson := RESTResponse1.JSONValue as TJSONObject;
    str:= objJson.Values['data'].Value;
    Mais le problème ne vient pas de la ligne "str:=...", j'ai le message d'erreur sur "objJson := RESTResponse1.JSONValue as TJSONObject;" avec la variable "objJson : TJSONObject;"

  2. #2
    Rédacteur/Modérateur

    Bonjour,

    rapidement j'aurai mis un toString
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    str:= objJson.Values['data'].Value.ToString;

    mais je n'ai pas vraiment l'habitude de passer par des Objets JSON non plus me contentant d'utiliser RESTDebugger qui me produit les composants nécessaires
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio, Sidney) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  3. #3
    Expert éminent sénior
    je ne connais pas JSONObject...mais cette réponse JSON est un array [] qui contient un seul objet {} donc ton code est forcément faux puisque tu cherches à lire un objet au lieu d'un tableau d'objets
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #4
    Membre extrêmement actif
    Citation Envoyé par SergioMaster Voir le message
    Bonjour,

    rapidement j'aurai mis un toString
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    str:= objJson.Values['data'].Value.ToString;

    mais je n'ai pas vraiment l'habitude de passer par des Objets JSON non plus me contentant d'utiliser RESTDebugger qui me produit les composants nécessaires
    Jusqu'à maintenant, j'utilisais également REST sans utiliser JSON mais j'ai été confronté à une limite imprévue qui est bonne à savoir donc j'en parle ici...

    Pour résumer, ma réponse REST était envoyée dans un clientdataset et je récupérais les données par des "str:=ClientDataset1.FieldValues['data'];"... mais avec cette approche ton string "data" est limité à... 255 caractères!

    D'où ma quête dans les méandres de l'usage de REST/JSON

  5. #5
    Membre extrêmement actif
    Citation Envoyé par Paul TOTH Voir le message
    je ne connais pas JSONObject...mais cette réponse JSON est un array [] qui contient un seul objet {} donc ton code est forcément faux puisque tu cherches à lire un objet au lieu d'un tableau d'objets
    Tu a raison mais le problème se déclenche avant d'avoir à traiter l'aspect tableau...

    Mon code se base sur un code "vendu" comme fonctionnel qui avait la forme suivante:


    objJson := RESTResponse1.JSONValue as TJSONObject;
    dataJson := objJson.Values['header'] as TJSONObject;
    str:= dataJson.Values['data'].Value;
    Donc on récupère le tableau dans"obJson" (et là j'ai l'erreur de transtypage), on récupère dans "objson" l'objet "datajson" et ensuite on récupère la valeur "header" de "datajson".

    Ce code est vieux de 4 ans. Peut-être qu'il fonctionnait sur les anciennes versions de Delphi...

  6. #6
    Membre expérimenté
    m'intrigue : tout dans TJSONxxx retourne des TJSONValues, donc dans la ligne récupérant la chaine, j'aurais trans type en TJSONString avant d'en récupérer le values. à vérifier

  7. #7
    Membre extrêmement actif
    Delphi 10.3.3 est livré avec un exemple utilisant REST et json: RESTDemos

    Je compile le projet qui propose différents exemples d'utilisation de REST, ils fonctionnent sauf l'exemple utilisant JSON qui se termine en erreur.

    Je reprends le code et l'insère dans mon application

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var
      LValues: TJSONArray;
      LJson: TJSONObject;
      LTempSensorName: string;
      LValue: TJsonValue;


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      LJson := RESTRequest.Response.JSONValue as TJSONObject;
      LValues := LJson.Values['values'] as TJSONArray;
      for LValue in LValues do
      begin
        // the sensor values are not objects unfortunately, but arrays of strings
        if (LValue as TJSONArray).Items[0].Value = LTempSensorName then
        begin
          LTemp := StrToInt((LValue as TJSONArray).Items[1].Value) / 100;
          Lbl_Temperature.Caption := Format('%3.0f°F', [LTemp]);
          break;
        end;
      end;


    Et cela se termine par un "Transtypage erreur" sur la première ligne "LJson := RESTRequest.Response.JSONValue as TJSONObject;"

    Je ne peux même pas récupérer la réponse REST dans une variable de type TJSONObject sous la forme d'un TJSONObject !!!

    Cela laisse songeur...

  8. #8
    Expert éminent sénior
    il faudrait faire du pas à pas dans RESTRequest.Response.JSONValue car tu as probablement une réponse à nil et l'exception indique que nil n'est pas un TJSONObject

    ou au minimum voir l'exception en mode debug car, s'il y en a une, est masquée

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    function TCustomRESTResponse.GetJSONValue: TJsonValue;
    var
      LTemp: Boolean;
    begin
      Result := nil;
      if Content <> '' then
        try
          GetJSONResponse(Result, LTemp);
        except
          // This method ignores exceptions
        end;
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #9
    Membre extrêmement actif
    Le problème semble avoir pour origine que le format du JSON envoyé par le serveur n'est pas compatible avec le "JSON made in Delphi"!

    J'ai trouvé un exemple qui fonctionne avec code et "JSON qui convient" et le JSON comporte des "\" que je n'ai vu dans aucun exemple de fichier JSON


    const
    response =
    '{"result":["[{\"email\":\"XXX@gmail.com\",\"regid\":\"12312312312312312313213w\"},'+ '{\"email\":\"YYYY@gmail.com\",\"regid\":\"AAAAAAA\"}]"]}';

    response_bis =
    '{"result":["[{"email":"XXX@gmail.com","regid":"12312312312312312313213w"},'+ '{"email":"YYYY@gmail.com","regid":"AAAAAAA"}]"]}';

    var
    LResult: TJSONArray;
    LJsonResponse: TJSONObject;
    ja: TJSONArray;
    jv: TJSONValue;

    begin

    LJsonResponse := TJSONObject.ParseJSONValue(response) as TJSONObject;
    LResult := LJsonResponse.GetValue('result') as TJSONArray;
    ja := TJSONObject.ParseJSONValue(LResult.Items[0].Value) as TJSONArray;
    for jv in ja do begin
    memo1.Lines.Add(jv.GetValue<string>('email'));
    memo1.Lines.Add(jv.GetValue<string>('regid'));
    end;
    end;
    Le même code traitant un JSON provenant de différents serveurs de test via REST donne un "Transtypage erreur" sur la ligne "LJsonResponse := TJSONObject.ParseJSONValue(response) as TJSONObject;"

    Le même code avec le "JSON qui convient" sans les "\" (=response_bis) et on se retrouve avec un "Violation d'accès"...

    Je me demande s'il ne faut pas tout simplement oublier le traitement JSON via les fonctions fournies par Delphi!

  10. #10
    Expert éminent sénior
    Ce message n'a pas pu être affiché car il comporte des erreurs.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  11. #11
    Membre extrêmement actif
    Je fais profiter les Delphistes de la solution ("bricolage" serait un meilleur terme) que j'ai trouvé pour résoudre mon problème de Transtyping error.

    Je confirme que le problème provient du format de la réponse JSON envoyée par le serveur. Il y a apparemment JSON et JSON pour certains Le JSON retrourné n'a pas un format "{"result":[...]}" mais "{[...]}".

    Solution:

    1. Je récupère le JSON envoyé par le serveur par un "str:=RESTResponse1.JSONText;"

    2. J'adapte le string: "{[...]}" devient "{"result":[...]}"

    3. Je transforme le string modifié en un TJSONValue par un "JSONValue := TJSonObject.ParseJSONValue(str);" (Eureka! il n'y a plus de "Transtyping error")

    4. Je récupère les valeurs dans JSONValue par du code du genre "str1 := JsonValue.GetValue<string>('results[0].header');"


    Merci aux divers intervenants qui m'ont proposé leur aide.

###raw>template_hook.ano_emploi###