«
»
Lecture JSON

Lecture JSON

Malgré l’existence des fonctions JSONVersVariant et VariantVersJSON (qui ne fonctionnent pas toujours bien selon mon expérience en WD23), voici un bout de code permettant de retrouver une données dans un JSON selon son chemin.

PROCEDURE jLit(LOCAL sSourceJson est une chaîne,sCheminALire est une chaîne, sReponseSiPasTrouve est une chaîne = "", sCheminCourant est une chaîne="")
nPosVirgule,nPosCrochet,nPosAccolade,nPosOuvreAccolade,n,m,nElement,nCaract sont des entiers
sElement,sCode,sValeur,sSousElement sont des chaînes
 
nPosOuvreAccolade=Position(sSourceJson,"{"+Caract(34))
TANTQUE nPosOuvreAccolade>0
  sSourceJson=Milieu(sSourceJson,2)
  nPosVirgule=Position(sSourceJson,","+Caract(34));nPosCrochet=Position(sSourceJson,":[");nPosAccolade=Position(sSourceJson,":{")
  SI nPosVirgule=0 ALORS nPosVirgule=Position(sSourceJson,"}")
  TANTQUE nPosVirgule>0 OU nPosCrochet>0
    SI nPosVirgule>0 ET ((nPosCrochet=0 OU (nPosCrochet>0 ET nPosVirgule < nPosCrochet)) ET (nPosAccolade=0 OU (nPosAccolade>0 ET nPosVirgule < nPosAccolade))) ALORS sElement=Gauche(sSourceJson,nPosVirgule-1) sCode=Remplace(ExtraitChaîne(sElement,1,":"),Caract(34),"") sValeur=Milieu(sElement,Taille(sCode)+4) //car peut contenir des : comme une adresse web, +3 car 2 guillemets+: SI Gauche(sValeur,1)=Caract(34) ALORS sValeur=Milieu(sValeur,2) SI Droite(sValeur,1)=Caract(34) ALORS sValeur=Gauche(sValeur,Taille(sValeur)-1) SI sCheminALire~=sCheminCourant+["/"]+sCode ALORS RENVOYER sValeur SINON sSourceJson=Milieu(sSourceJson,nPosVirgule+1) SINON SI nPosAccolade>0 _ET_ (nPosCrochet=0 OU (nPosCrochet>0 ET nPosAccolade < nPosCrochet)) ALORS sCode=Remplace(Gauche(sSourceJson,nPosAccolade-1),Caract(34),"") sSourceJson=Milieu(sSourceJson,nPosAccolade+1) //on trouve l'accolade de fin n=Position(sSourceJson,"}");m=Position(sSourceJson,"{");nCaract=(m>0 ET m < n) //d'autres sous-élément si { avant un } TANTQUE nCaract>0
        n=Position(sSourceJson,"}",m+1);m=Position(sSourceJson,"{",m+1)
        SI (m>0 ET m < n) ALORS nCaract++ SINON nCaract--;m=n FIN FIN SI Position(sCheminALire,sCheminCourant+["/"]+sCode+"/")>0 ALORS
        RENVOYER jLit(Gauche(sSourceJson,n),sCheminALire,sReponseSiPasTrouve,sCheminCourant+["/"]+sCode)
      SINON
        sSourceJson=Milieu(sSourceJson,n+2)
      FIN
    SINON SI nPosCrochet>0 ALORS
      sCode=Remplace(Gauche(sSourceJson,nPosCrochet-1),Caract(34),"")
      sSourceJson=Milieu(sSourceJson,nPosCrochet+1)
      //on trouve le crochet de fin
      n=Position(sSourceJson,"]");m=Position(sSourceJson,"[");nCaract=(m>0 ET m < n) //d'autres sous-élément si { avant un } TANTQUE nCaract>0
        n=Position(sSourceJson,"]",m+1);m=Position(sSourceJson,"[",m+1)
        SI (m>0 ET m < n) ALORS nCaract++ SINON nCaract--;m=n FIN FIN SI Position(sCheminALire,sCheminCourant+["/"]+sCode+"[")>0 ALORS
        SI n>0 ET (n < =m OU m=0) ALORS sSousElement=Milieu(sSourceJson,2,n-2);nElement=0 SINON SI n=0 ALORS n=Position(sSourceJson,"}");m=Position(sSourceJson,"{");nCaract=(m>0 ET m < n) //d'autres sous-élément si { avant un } TANTQUE nCaract>0
            n=Position(sSourceJson,"}",m+1);m=Position(sSourceJson,"{",m+1)
            SI (m>0 ET m < n) ALORS nCaract++ SINON nCaract--;m=n FIN FIN sSousElement=Gauche(sSourceJson,n) SINON //problème, on a pas trouvé le crochet de fin RENVOYER sReponseSiPasTrouve FIN BOUCLE m=Position(sSousElement,"{") SI m>0 ALORS
            nElement++;m=1
            n=Position(sSousElement,"}",m+1);m=Position(sSousElement,"{",m+1)
            SI m>0 _ET_ m < n ALORS
              nCaract=1
              TANTQUE nCaract < >-1
                n=Position(sSousElement,"}",m+1);m=Position(sSousElement,"{",m+1)
                SI (m>0 ET m < n) ALORS nCaract++ SINON nCaract--;m=n FIN FIN FIN SI n>0 ALORS
              SI Position(sCheminALire,sCheminCourant+["/"]+sCode+"["+nElement+"]")>0 ALORS 
                RENVOYER jLit(Gauche(sSousElement,n),sCheminALire,sReponseSiPasTrouve,sCheminCourant+["/"]+sCode+"["+nElement+"]")
              FIN
              sSousElement=Milieu(sSousElement,n+2)  //+2 correspond au },
            SINON
              SORTIR
            FIN
          SINON 
            POUR TOUTE CHAÎNE sValeur DE sSousElement SEPAREE PAR Caract(34)+","+Caract(34)
              nElement++
              SI Position(sCheminALire,sCheminCourant+["/"]+sCode+"["+nElement+"]")>0 ALORS RENVOYER Remplace(sValeur,Caract(34),"")
            FIN
            RENVOYER sReponseSiPasTrouve
          FIN
        FIN
 
      SINON
        sSourceJson=Milieu(sSourceJson,n+2)
      FIN
    FIN
    nPosVirgule=Position(sSourceJson,","+Caract(34));nPosCrochet=Position(sSourceJson,":[");nPosAccolade=Position(sSourceJson,":{")
    SI nPosVirgule=0 ALORS nPosVirgule=Position(sSourceJson,"}")  //pour la dernière accolade
  FIN
  nPosOuvreAccolade=Position(sSourceJson,"{"+Caract(34),nPosOuvreAccolade)
FIN
RENVOYER sReponseSiPasTrouve

Son usage est très simple : il suffit de donner le chemin de la donnée pour avoir son résultat. Exemple jLit(sResHTML, »client/commande[1]/numero »).

Les paramètres :
sSourceJson : le résultat que vous avez obtenu en faisant une requête (typiquement, le contenu de HTTPDonneRésultat(httpRésultat))
sCheminALire : voir exemple ci-dessus. Le « [1] » correspond à la première commande, mettre donc « [2] » pour la seconde commande et ainsi de suite. S’il n’y a pas d’occurrence, juste enlever le chiffre entre crochet : jLit(sResHTML, »client/commande/numero »)
sRéponseSiPasTrouvé : ce que renvoie la fonction si la valeur du chemin n’a pas été trouvé (car elle n’existe pas ou est indéxée ou …)
sCheminCourant : chemin qui est passé lors d’une seconde lecture de la procédure (elle est récursive) > ne pas renseigner lors de l’appel.