Ça fait plusieurs fois que je vois que certains ont des difficultés pour parser du Json.

Dernièrement par rapport à une demande pour parser un flux d'allocine, j'ai fait une réponse qui bien que fonctionnelle ne me convenait pas.
http://www.developpez.net/forums/d13...page-internet/

Du coup j'ai profité d'un week-end pluvieux pour pousser la réflexion un peu plus loin.

La contribution consiste en un procédure JsonLit() un peut similaire à la fonction existante XMLLit().
Cette procédure a 3 paramètres :
- sSourceJson = chaîne contenant le code Json à analyser.
- sChemin_elem_a_lire = chaîne contenant une requête à exécuter qui ressemble à XPath.
- sReponse_si_non_trouve = texte à renvoyer si l'élément n'a pas été trouvé. Ce paramètre est optionnel, par défaut, il correspond à une chaîne vide ("").

Exemple de requête XPath :
/COMMANDE/NUMEROCDE -----------------> Sélectionne la rubrique NUMEROCDE de la COMMANDE
/COMMANDE/LIGNECDE[2]/NUMEROLIGNE ---> Sélectionne la rubrique NUMEROLIGNE de la 2ème LIGNECDE de la COMMANDE

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
PROCEDURE JsonLit(sSourceJson est une chaîne,sChemin_elem_a_lire est une chaîne,sReponse_si_non_trouve est une chaîne = "")
 
// sSourceJson sans les {/} début/fin 
sSourceJson_extrait est une chaîne = Milieu(sSourceJson,2, Taille(sSourceJson) - 2)
 
nSourceJson_extrait_taille est un entier
sSourceJson_sous_chaine est une chaîne
sSous_chaine est une chaîne
bTrouve est un booléen = Vrai
sElement est une chaîne
sElement_extrait est une chaîne
nElement_nb est un entier
nElement_no_ligne est un entier
nPosition_debut est un entier
nPosition_fin est un entier
nPosition_debut_parenthese_crochet est un entier
sPile est une chaîne
i,j est un entier
 
nElement_nb = ChaîneOccurrence(sChemin_elem_a_lire,"/")
sElement    = ExtraitChaîne(sChemin_elem_a_lire,rangPremier,"/")
sElement    = ExtraitChaîne(sChemin_elem_a_lire,rangSuivant,"/")
TANTQUE sElement <> EOT
	i += 1
	nPosition_debut = Position(sElement,"[")
	nPosition_fin   = Position(sElement,"]")
	SI nPosition_debut = 0 ET nPosition_fin = 0 ALORS
		sElement_extrait  = sElement
		nElement_no_ligne = 0
	SINON SI nPosition_debut > 0 ET nPosition_fin > 0 ALORS
		sElement_extrait  = Gauche(sElement,nPosition_debut - 1)
		nElement_no_ligne = Val(Milieu(sElement,nPosition_debut + 1,nPosition_fin - 1))
	SINON
		// Élément avec crochet manquant RETOUR
		RENVOYER sReponse_si_non_trouve
	FIN
 
	nPosition_debut = Position(sSourceJson_extrait,"""" + sElement_extrait + """:")
	SI nPosition_debut = 0 ALORS
		// Élément non trouvé RETOUR
		RENVOYER sReponse_si_non_trouve	
	SINON
		nSourceJson_extrait_taille = Taille(sSourceJson_extrait)
		sSourceJson_sous_chaine   = Milieu(sSourceJson_extrait,nPosition_debut + Taille(sElement_extrait) + 3, 1)
		SELON sSourceJson_sous_chaine
			CAS "{"
		 		// Objet
		 		nPosition_debut_parenthese_crochet = Position(sSourceJson_extrait,"{",nPosition_debut)
		 		sPile = ""
		 		POUR j = nPosition_debut_parenthese_crochet A nSourceJson_extrait_taille
		 			sSous_chaine = Milieu(sSourceJson_extrait, j, 1)
		 			SELON sSous_chaine
		 				CAS "{", "["
		 					sPile += sSous_chaine
		 				CAS "}", "]"
		 					SI Droite(sSous_chaine,1) = sSous_chaine ALORS
		 						sPile = Gauche(sPile,Taille(sPile) - 1)
		 					SINON
		 						// Mauvaise chronologie des {[]} RETOUR
								RENVOYER sReponse_si_non_trouve
		 					FIN
		 			FIN
		 			SI sPile = "" ALORS
		 				nPosition_fin = j
		 				SORTIR
		 			FIN	
		 		FIN
		 		SI sPile <> "" ALORS
					// Mauvaise chronologie des {[]} RETOUR
		 			RENVOYER sReponse_si_non_trouve
		 		FIN
		 		// récupère l'objet sans les {/} début/fin et passe à l'élément suivant
		 		sSourceJson_extrait = Milieu(sSourceJson_extrait,nPosition_debut_parenthese_crochet + 1, nPosition_fin - nPosition_debut_parenthese_crochet - 1)		 		
 
			CAS "["
		 		// Tableau
		 		SI nElement_no_ligne = 0 ALORS
					RENVOYER sReponse_si_non_trouve
		 		FIN
				nPosition_debut_parenthese_crochet = Position(sSourceJson_extrait,"[",nPosition_debut)
				sPile = ""
				POUR j = nPosition_debut_parenthese_crochet A nSourceJson_extrait_taille
					sSous_chaine = Milieu(sSourceJson_extrait, j, 1)
					SELON sSous_chaine
						CAS "{", "["
							sPile += sSous_chaine
						CAS "}", "]"
							SI Droite(sSous_chaine,1) = sSous_chaine ALORS
								sPile = Gauche(sPile,Taille(sPile) - 1)
							SINON
								// Mauvaise chronologie des {[]} RETOUR
								RENVOYER sReponse_si_non_trouve
							FIN
					FIN
					SI sPile = "" ALORS
						nPosition_fin = j
						SORTIR
					FIN	
				FIN
				SI sPile <> "" ALORS
					// Mauvaise chronologie des {[]} RETOUR
					RENVOYER sReponse_si_non_trouve
				FIN
				// récupère toutes les lignes du tableau sans les [{/}] début/fin 
				sSourceJson_extrait = Milieu(sSourceJson_extrait,nPosition_debut_parenthese_crochet + 2, nPosition_fin - nPosition_debut_parenthese_crochet - 3)
		 		// récupère le numéro de ligne demandé dans le tableau et passe à l'élément suivant
		 		sSourceJson_extrait = ExtraitChaîne(sSourceJson_extrait,nElement_no_ligne,"},{")	 		
 
			CAS """"
		 		// Valeur chaine
		 		SI i <> nElement_nb ALORS
		 			// Valeur pas sur dernier élément du chemin RETOUR
		 			RENVOYER sReponse_si_non_trouve
		 		FIN
		 		nPosition_debut = nPosition_debut + Taille(sElement_extrait) + 4
		 		nPosition_fin   = 0
				SI Position(sSourceJson_extrait,""",",nPosition_debut) > 0 ALORS
					nPosition_fin = Position(sSourceJson_extrait,""",",nPosition_debut)
				FIN		
				SI Position(sSourceJson_extrait,"""},",nPosition_debut) > 0 ET Position(sSourceJson_extrait,"""},",nPosition_debut) < nPosition_fin ALORS
					nPosition_fin = Position(sSourceJson_extrait,"""},",nPosition_debut)
				FIN
				SI Position(sSourceJson_extrait,"""}],",nPosition_debut) > 0 ET Position(sSourceJson_extrait,"""}],",nPosition_debut) < nPosition_fin ALORS
					nPosition_fin = Position(sSourceJson_extrait,"""}],",nPosition_debut)
				FIN
				SI nPosition_fin = 0 ALORS
					nPosition_fin = Taille(sSourceJson_extrait)
				FIN
				// valeur trouvée	
		 		RENVOYER Milieu(sSourceJson_extrait,nPosition_debut,nPosition_fin - nPosition_debut)		 		
 
			AUTRE CAS
		 		// valeur numérique
				SI i <> nElement_nb ALORS
					// Valeur pas sur dernier élément du chemin RETOUR
					RENVOYER sReponse_si_non_trouve
				FIN
				nPosition_debut = nPosition_debut + Taille(sElement_extrait) + 3
				nPosition_fin   = 0
				SI Position(sSourceJson_extrait,",",nPosition_debut) > 0 ALORS
					nPosition_fin = Position(sSourceJson_extrait,",",nPosition_debut)
				FIN		
				SI Position(sSourceJson_extrait,"},",nPosition_debut) > 0 ET Position(sSourceJson_extrait,"},",nPosition_debut) < nPosition_fin ALORS
					nPosition_fin = Position(sSourceJson_extrait,"},",nPosition_debut)
				FIN
				SI Position(sSourceJson_extrait,"}],",nPosition_debut) > 0 ET Position(sSourceJson_extrait,"}],",nPosition_debut) < nPosition_fin ALORS
					nPosition_fin = Position(sSourceJson_extrait,"}],",nPosition_debut)
				FIN
				SI nPosition_fin = 0 ALORS
					nPosition_fin = Taille(sSourceJson_extrait) + 1
				FIN
				// valeur trouvée	
				RENVOYER Milieu(sSourceJson_extrait,nPosition_debut,nPosition_fin - nPosition_debut)
		 FIN			 
	FIN
	sElement = ExtraitChaîne(sChemin_elem_a_lire,rangSuivant,"/")
FIN
 
RENVOYER sReponse_si_non_trouve
exemple d'appel de la procédure pour parser un flux d'allocine (en l’occurrence tous les filmes correspondant au mot avatar) pour remplir un table

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
sChaine_reponse est une chaîne
nNb_film,i est un entier
sURL sont des chaîne = ChaîneConstruit("http://api.allocine.fr/rest/v3/search?partner=YW5kcm9pZC12M3M&filter=movie&q=%1&format=json","avatar")
 
TableSupprimeTout(TABLE_Film)
 
// Lance la requête
SI PAS HTTPRequête(sURL) ALORS
	Erreur(ErreurInfo())
	RETOUR
FIN
// Récupère le résultat de la requête
sChaine_reponse = HTTPDonneRésultat(httpRésultat)
 
nNb_film = JsonLit(sChaine_reponse,"/feed/count")
 
POUR i = 1 A nNb_film
	TableAjouteLigne(TABLE_Film,JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/code"), ...
								JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/originalTitle"), ...
								JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/title"), ...
								JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/productionYear"), ...
								Remplace(JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/release/releaseDate"),"-",""), ...
								JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/castingShort/directors"), ...
								JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/castingShort/actors"), ...
								JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/statistics/pressRating"), ...
								JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/statistics/userRating"), ...
								Remplace(JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/poster/href"),"/",""), ...
								Remplace(JsonLit(sChaine_reponse,"/feed/movie[" + i + "]/link[1]/href"),"/",""))
FIN
Attention ce code n'est pas forcément exhaustif pour parser du Json.
Je n'ai pas repris un algorithme existant. J'ai juste observé le flux d'allocine que j'ai interprété.
Sur ce flux ce code fonctionne bien. Il repère les objets, les tableaux, et les rubriques contenant des valeurs.

Lors de toute 1ère utilisation je vous conseille de vous assurer que le format est bien reconnu et que les données retournées sont bien conformes à celles contenues dans le fichier Json.

Si certains veulent améliorer/compléter cette contribution j'en serais ravi...
Le traitement a un peu de lenteur qui peut être important sur des très gros fichiers. Il y a sans doute possibilité d’accélérer cette vitesse de traitement.

Bonne utilisation.