Page 1 sur 1

[resolu] Interpréter un JSON via HTTPRequest

Publié : dim. 07/juin/2020 14:24
par Ar-S
Salut,

Je suis paumé dans l'utilisation de HTTPRequestMemory pour récupérer les données d'un json générées via un URL

Jusqu'ici je lançais un HTTPRequest

Code : Tout sélectionner

 Request = HTTPRequest(#PB_HTTP_Get, UserUrl$)
 If Request
   If HTTPInfo(Request, #PB_HTTP_StatusCode) = "200"
     HTML$ = HTTPInfo(Request, #PB_HTTP_Response)
     
     Debug HTML$
endif
endif
Le résultat d'HTML$ est bien un contenu de JSON sous cette forme (en une seule ligne)

Code : Tout sélectionner

{
    "Code": 0,
    "message": "OK",
    "data": {
        "champ1": "donnee1",
        "champ2": "donnee2",
        "champ3": "donnee3",
        "champ4": "donnee4"
    }
}
Mais je ne vois pas comment interpréter ce contenue JSON vu que je n'ai pas fait de load/catch JSON
Et comme je ne veux pas écrire sur le disque dur, je me dit qu'il faut que j'utilise HTTPRequestMemory histoire de pouvoir ensuite faire un CatchJson.

Mais la doc n'a pas d'exemple pour HTTPRequestMemory
Resultat = HTTPRequestMemory(Type, URL$ [, *Data, TailleData [, Options [, EnTetes()]]])

.. Je ne vois pas trop comment indiquer TailleData et quoi foutre en EnTetes
Sachant que si j'ai bien compris, c'est le *Data , TailleData qui me serviront dans le catchJson..

Peut être que je me trompe complètement dans mon process mais j'aimerai comprendre.

(pour le moment je parsais le contenu d'HTML$ à coup de findstring/mid etc. ça marche mais c'est dommage de se priver d'une fonction existante.)

Merci de m'éclairer.

Re: Comment récupérer un JSON via HTTPRequestMemory

Publié : dim. 07/juin/2020 19:22
par Naheulf
Si j'ai bien compris, HTTPRequestMemory() c'est lorsque tu veut faire des requêtes de type "POST" et que les données à envoyer sont dans la mémoire.

On a (si j'ai bien compris) :
  • *data : pointeur vers les données à envoyer
  • tailleData : taille brute des données à envoyer
Aux options près, et si je ne me plante pas sur le fonctionnement du protocole HTTP, on a donc :

Code : Tout sélectionner

HTTPRequestMemory(Type, URL$ [, *Data, TailleData [, OptionsHTTP [, EnTetes()]]])
qui équivaut à faire

Code : Tout sélectionner

HTTPRequest(Type, URL$ [, Base64Encoder(*Data, TailleData [, Options64]) [, OptionsHTTP [, EnTetes()]]])
Édit : Le Base64 ne servant que pour transmettre les données binaires susceptible de contenir des codes pouvant interférer avec la bonne gestion/transmission de la requête.

Re: Comment récupérer un JSON via HTTPRequestMemory

Publié : dim. 07/juin/2020 19:37
par Marc56
Je comprends peut-être (encore) de travers, mais si ce que tu veux faire est ne pas écrire de fichier sur le disque dur, il n'y a pas de problème car le contenu retour de HTTPRequest se fait dans une variable chaine de caractères.
Après tu peux extraire les données avec les fonctions JSON ou les fonction texte.

Code : Tout sélectionner

InitNetwork()

UserUrl$ = "http://127.0.0.1/Test_Ar-S.php"

Request = HTTPRequest(#PB_HTTP_Get, UserUrl$)
If Request
    If HTTPInfo(Request, #PB_HTTP_StatusCode) = "200"
        HTML$ = HTTPInfo(Request, #PB_HTTP_Response)
        
        Debug HTML$
    EndIf
EndIf

For i = 1 To CountString(HTML$, #CRLF$)
    Debug "Ligne #" + i + " " + StringField(HTML$, i, #CRLF$)
Next

Code : Tout sélectionner

{
    "Code": 0,
    "message": "OK",
    "data": {
        "champ1": "donnee1",
        "champ2": "donnee2",
        "champ3": "donnee3",
        "champ4": "donnee4",
    }
}
Ligne #1 {
Ligne #2     "Code": 0,
Ligne #3     "message": "OK",
Ligne #4     "data": {
Ligne #5         "champ1": "donnee1",
Ligne #6         "champ2": "donnee2",
Ligne #7         "champ3": "donnee3",
Ligne #8         "champ4": "donnee4",
Ligne #9     }
Différence entre les deux fonctions (dixit l'aide)
HTTPRequest Envoie une requête HTTP avec des données textuelles optionnelles.
HTTPRequestMemory Envoie une requête HTTP avec des données binaires optionnelles.

Quant à la différence entre POST et GET. Principales différences et usages:
- GET envoie les données dans l'URL (donc utile pour bookmarker, mais laisse les données envoyée visibles)
- POST envoie les données dans le corps du message (données invisibles aux intermédiaires (ie: proxy)) mais on ne peut pas bookmarker car les données n'existent que lors de l'envoi.

Pour plus de détails c'est mieux expliqué ici que dans les textes en français
https://www.w3schools.com/tags/ref_httpmethods.asp

:wink:

Re: Comment récupérer un JSON via HTTPRequestMemory

Publié : dim. 07/juin/2020 22:00
par Ar-S
HTTPRequestMemory() c'est lorsque tu veux faire des requêtes de type "POST"
Ahlàlà j'ai occulté le POST...

Une chose est sûr, je n'aime pas du tout la syntaxe Json et encore moins leurs traitements, mais alors pas du tout...
En attendant une réponse j'ai utilisé des stringfield (à la place de mes vieux findstring) et j'ai solutionné mon soucis.

Code : Tout sélectionner

truc$ = RemoveString (StringField(HTML$, 4, ",") , "champ1:") pour obtenir "donnees1"
Merci pour tes éclaircissements, on arrive à la même conclusion pour le traitement ce qui me rassure.

Re: Comment récupérer un JSON via HTTPRequestMemory

Publié : lun. 08/juin/2020 15:28
par case
ça ne marchera que si tes données par exemple des chaines de caractères ne contiennent pas de virgule.
sinon ton stringfield vas couper ta donnée en deux et cela décalera tout le reste.
:mrgreen:

Re: Comment récupérer un JSON via HTTPRequestMemory

Publié : lun. 08/juin/2020 20:38
par Ar-S
Les données que je récup sont toujours formatés de la même manière. Pas de risque. (sinon j'aurai fait plus de vérif ;))

Re: Comment récupérer un JSON via HTTPRequestMemory

Publié : mar. 09/juin/2020 9:43
par Marc56
Juste pour le côté fun, la version regex pour extraire l'objet même s'il y a une virgule dedans.
Pour extraire un autre objet, changes "champ1" dans la regex

Note: Test_A.php est un simple fichier texte contenant ton JSON (corrigé de la virgule en trop qui le met en erreur "donnee4",). Ce fichier est sur un serveur web local (Apache + PHP)

Code : Tout sélectionner

InitNetwork()

UserUrl$ = "http://127.0.0.1/Test_A.php"

Request = HTTPRequest(#PB_HTTP_Get, UserUrl$)
If Request
    If HTTPInfo(Request, #PB_HTTP_StatusCode) = "200"
        HTML$ = HTTPInfo(Request, #PB_HTTP_Response)
    EndIf
EndIf

If CreateRegularExpression(0, 
                           ~"\"data\".+\"champ1\".+?\"(.+?)\"", 
                           #PB_RegularExpression_DotAll)
    
    If ExamineRegularExpression(0, HTML$)
        While NextRegularExpressionMatch(0)
            Debug RegularExpressionGroup(0, 1)
        Wend    
    EndIf
    
    FreeRegularExpression(0)
Else
    Debug RegularExpressionError()
EndIf

End
PS. Il faut tester les erreurs JSON après un Parse... car sinon, le système n'affiche rien et on pense à une données absente.

Code : Tout sélectionner

If ParseJSON(0, HTML$, #PB_JSON_NoCase)
   ...
Else
    Debug "Erreur   : " + JSONErrorMessage()
    Debug "Ligne    : " + JSONErrorLine()
    Debug "Position : " + JSONErrorPosition()
    End
EndIf
(Je n'aime pas non plus le format JSON et ses fonctions de gestion)
:wink:

Re: Comment récupérer un JSON via HTTPRequestMemory

Publié : mar. 09/juin/2020 9:55
par Ar-S
J'ai effectivement mis une virgule de trop dans mon exemple. Merci de l'avoir signalé. C'est corrigé.
Merci pour cet exemple de regex. J'y ai pensé quand le json me pompait, mais vu le format fixe des requêtes et des retours, le stringfield reste mon choix de prédilection.

Re: Comment récupérer un JSON via HTTPRequestMemory

Publié : dim. 06/déc./2020 18:30
par falsam
Je déterre ce sujet suite à une conversation avec Ar-s aujourd'hui sur le serveur Discord de PureBasic.

Ar-s cherche à récupérer des données HTTP au format JSON dans une structure PB.

n'ayant pas le lien pour downloader les données, j'ai mis un exemple des données dans un fichier texte.

Code : Tout sélectionner

{
   "statusCode":0,
   "message":"Success",
   "data":{
      "list":[
         {
            "file_code":"cb3137715",
            "file_name":"nomfichier.ext",
            "file_size":23351305,
            "available_uts":true,
            "need_premium":false,
            "subtitles":[
               {
                  "type":"vtt",
                  "src":"https://www34.url/suite.vtt",
                  "label":"Forced",
                  "srcLang":"fre"
               },
               {
                  "type":"vtt",
                  "src":"https://www34.url/suite.vtt",
                  "label":"French",
                  "srcLang":"fre"
               }
            ]
         }
      ]
   }
}
Décryptage du JSON.

- "statusCode" -> Integer
- "message" -> String
-- "data" -> Object
--- "list" -> Array
---- "subtitles" -> Array

Code.

Code : Tout sélectionner

EnableExplicit

Structure Def_SubTitles
  type.s
  src.s
  label.s
  srcLang.s
EndStructure

Structure Def_List
  file_code.s 
  file_name.s 
  file_size.i 
  available_uts.b
  need_premium.b
  Array subtitles.Def_SubTitles(0)
EndStructure

Structure Def_Data
  Array List.Def_List(0)
EndStructure 

Structure NewRecord 
  statusCode.i
  message.s
  Data.Def_Data
EndStructure

Define Record.Newrecord

; Chargement du fichier
Define Result = LoadJSON(#PB_Any, "test.json", #PB_JSON_NoCase )

; Chargement dans la structure associée
ExtractJSONStructure(JSONValue(Result), Record, NewRecord)

; Vérification de l'intégrité du JSON
Debug ComposeJSON(Result, #PB_JSON_PrettyPrint)
Debug #CRLF$

; Debug 
Debug "Debug de quelques items"

Debug Record\statusCode
Debug Record\message
Debug Record\Data\List(0)\file_name
Debug Record\Data\List(0)\subtitles(0)\src

Re: Comment récupérer un JSON via HTTPRequestMemory

Publié : dim. 06/déc./2020 18:36
par falsam
Il est possible de ne pas définir l'intégralité des données reçues.

Code : Tout sélectionner

EnableExplicit

Structure Def_List
  file_code.s 
  file_name.s 
EndStructure

Structure Def_Data
  Array List.Def_List(0)
EndStructure 

Structure NewRecord 
  Data.Def_Data
EndStructure

Define Record.Newrecord

; Chargement du fichier
Define Result = LoadJSON(#PB_Any, "test.json", #PB_JSON_NoCase )

; Chargement dans la structure associée
ExtractJSONStructure(JSONValue(Result), Record, NewRecord)

; Debug 
Debug "Debug de quelques items"

Debug Record\Data\List(0)\file_code
Debug Record\Data\List(0)\file_name

Re: Comment récupérer un JSON via HTTPRequestMemory

Publié : dim. 06/déc./2020 21:16
par Ar-S
Merci Falsam. Avec le code de Naheulf et le tiens je vais tâcher de piger le fonctionnement.