
Intégration JSON à IBM i.
Projet YAJL
Scott Klement (l'auteur du projet JDBCR4) propose l'Implémentation du projet Open Source YAJL (écrit en C) sur IBM i
Yet Another JSON Library
Ainsi qu'un programme de service qui sert de passerelle, écrit en RPG pour RPG : YAJLR4
JSON (JavaScript Object Notation) est un format de données textuelles dérivé de la notation des objets du langage JavaScript (Wikipedia) |
ce qui s'écrit comme cela en XML |
|
s'écrit comme cela en JSON |
<producteurs>
<producteur>
<numero>45</numero>
<commune>Reims</commune>
<appellation>13</appellation>
</producteur>
</producteurs> |
-> |
{
"producteurs": {
"producteur": {
"numero":45,
"commune":"Reims",
"appellation":13
}
}
} |
Un élément peut contenir un objet, une valeur ou un tableau de valeurs, marqué alors par [ et ]
<PO>
<id>103</id> <orderDate>2014-06-20</orderDate> <customer> <cid>888</cid> </customer>
<items> <item> <partNum>872-AA</partNum> <shipDate>2014-06-21</shipDate> <productName>Lawnmower</productName> <USPrice>749.99</USPrice> <quantity>1</quantity> </item> <item> <partNum>837-CM</partNum> <productName>Digital Camera</productName> <USPrice>199.99</USPrice> <quantity>2</quantity> <comment>2014-06-22</comment> </item> </items> </PO> |
devient (remarquez le tableau de "item")
{
"PO":{
"id": 103,
"orderDate": "2014-06-20",
"customer": {"@cid": 888},
"items": {
"item": [
{ "partNum": "872-AA",
"productName": "Lawnmower",
"quantity": 1,
"USPrice": 749.99,
"shipDate": "2014-06-21"
},
{ "partNum": "837-CM",
"productName": "Digital Camera",
"quantity": 2,
"USPrice": 199.99,
"comment": "2014-06-22"
}
]
}
}
} |
Il y a trois manières officielles d'utiliser JSON sur IBM i :
- DB2nosql -- accès "nosql" en mode ligne de commandes
- Les API Java
- les fonctions SQL
YAJL propose une quatrième solution permettant un accès en RPG
Installation
Commencez par aller chercher le SAVF sur le site https://www.scottklement.com/yajl/
Créez une bibliothèque (Scott propose YAJLLIB) et restaurez par :
RSTOBJ OBJ(*ALL) SAVLIB(QTEMP) DEV(*SAVF) SAVF(<bib-savf>/YAJLLIB) RSTLIB(<bib-objet>)
Vérifiez que le répertoire de liage YAJL contient bien les deux programmes de services livrés
WRKBNDDIRE YAJL, puis option 9
Utilisation
Vos sources doivent commencer par
H DFTACTGRP(*NO) ACTGRP('xxxx') BNDDIR('YAJLLIB/YAJL')
ou
ctl-opt DFTACTGRP(*NO) ACTGRP('xxxx') BNDDIR('YAJLLIB/YAJL');
puis
/include yajl_h |
Création d'un document
- yajl_genOpen
- *ON le document contient des retours chariot (plus lisible)
- *OFF le document ne contient pas de retour chariot (plus compact)
- yajl_beginObj
- Début d'un objet ->

- dans un objet il peut y avoir :
- un booléen : yajl_addBool

- une chaîne : yajl_addChar

- un numérique yajl_addNum

- Un tableau yajl_addArray

le tableau est un tableau d'objet pouvant contenir :
- booléen
- numérique
- caractère
- tableau
- Les tableaux doivent être fermés
- yajl_endArray

- Les objets aussi
- yajl_endObj

- Enfin vous devez écrire quelque part le flux JSON, qui pour l'instant est en mémoire
- yajl_saveBuf
- 1er paramètre : fichier dans l'IFS
- 2eme paramètre : message d'erreur
- Pour terminer
- yajl_genClose

Exemple Complet
Partie déclaration (full Free RPG)

Structure générale du programme |
S/PGM (contient la API YAJL) |
 |
 |
Résultat
Avec Eclipse

Vous trouverez également des plugins plus intelligents (ici JSON Tools)

Lecture d'un document
- Chargement en mémoire d'un arbre JSON, puis lecture
- yajl_stmf_load_tree
- docNode représente donc un Objet JSON dans lequel on peut rechercher désormais, des nœuds
YAJL_object_find
- Nœud simple pour lequel on va pouvoir lire la donnée
- YAJL_is_true pour un booléen

- YAJL_get_string pour une chaîne

- YAJL_get_number pour un numérique
etc..
- Nœud de type Tableau
- qu'il faut parcourir avec YAJL_ARRAY_LOOP
- Enfin il faut libérer la mémoire par
- YAJL_tree_free

Exemple Complet
Partie déclaration (toujours full Free RPG)

Structure générale du programme

Boucle de lecture du tableau

Une fois la donnée lue, vous pouvez en faire ce que vous voulez (écriture, affichage, impression).
Pour un traitement du format XML par RPG, particulièrement le code opération XML-INTO, voyez ce cours
puis, en Mai 2018, IBM propose un code opération Data-Into permettant de parser n'importe quel format de données, à condition d'écrire le parser
Le produit YAJL s'adapte et propose un parser YAJLINTO pour ce code-opération
Soit le fichier suivant :

Le RPG suivant appelle le Parser

Remarquez count automatiquement renseigné dans la PSDS quand on alimente directement un tableau
Résultat

Vous pouvez mettre des options au parser
- "value_true" (dft="1")
Valeur pour true en JSON, par défaut le caractère 1
- "value_false" (dft="0")
Valeur pour false en JSON, par défaut le caractère 0
- "value_null" (dft=*NULL)
Valeur pour null en JSON, par défaut *NULL
Exemple d'utilisation d'options

(ne créez pas vos sources dans QRPGLESRC de YAJL, ce fichier est en CCSID 37, { et } ne seraient pas reconnus)
Résultat
- "skip_document_node" (dft = inactif)
Permet d"ignorer l'élément racine, traité dans le cas suivant

Sans l'option skip_document_node, vous devez faire une DS plus complexe
et cette dernière n'étant pas de type tableau, la PSDS ne contient plus le nombre d'occurences.
Il faut alors utiliser l'option countprefix (comme avec XML-INTO)