:: Enseignements :: Licence :: L3 :: 2013-2014 :: Programmation Objet avec Java ::
[LOGO]

URL et parsing JSON


Exercice 1 - Entrée sortie et ressource sur Internet

On cherche à copier des données de fichier à fichier ou à télécharger des données.

  1. Écrire une méthode copy qui prend en paramètre un InputStream et un OutputStream et copie les données de l'entrée vers la sortie.
    Pour tester, dans votre méthode main, vous utiliserez l'entrée standard et la sortie standard.
  2. Modifier votre main pour que, si il y a deux arguments sur la ligne de commande, le programme fasse la copie du contenu du fichier en premier argument vers le fichier en second argument.
  3. Modifier votre main pour que si le premier argument commence par "http://" ou "https://" le programme lise la ressource à l'URL correspondante.
  4. Modifier votre programme pour que, dans le cas où le premier argument est une URL, il affiche sur la sortie d'erreur standard l'entête de la réponse HTTP.

Exercice 2 - JSon parsing en mode Object Model

Utiliser le programme précédent pour aller lire à l'adresse
        https://api.github.com/search/repositories?q=rails
       
Attention à ce que le shell n'interprète pas les caractères !
Que se passe-t-il ?
Le document http://developer.github.com/v3/search/ vous explique le problème.
Comme je suis gentil, voilà une version offline du résultat de la requête query.json.

On cherche maintenant à extraire des informations du fichier texte au format JSON.
On va pour cela utiliser une bibliothèque externe de Parsing JSON que l'on peut trouver à l'adresse suivante https://jsonp.java.net/download.html.
Lisez bien la page pour charger le bon jar !


Créer un répertoire lib dans votre projet et déposer le jar dedans puis configurer Eclipse pour que les classes incluses dans le jar soit disponibles dans le build path. (Pour avoir les propriétés du projet: clic droit sur le projet puis Build Path).
La documentation au format JavaDoc correspondante se trouve à l'adresse https://json-processing-spec.java.net/nonav/releases/1.0/fcs/javadocs/index.html.

Un parseur JSON fonctionne suivant deux modes, un mode Object Model où l'ensemble des informations est monté en mémoire et un mode Stream Model où des évènements correspondants à la structure du document sont envoyés avec la possibilité de demander les valeurs pour ces évènements.

En mode Object Model on utilise un JsonReader
          JsonReader jsonReader = Json.createReader(Reader);
        
puis on utilise la méthode readObject() pour décoder le document.
On obtient alors un objet de type JsonObject qui fonctionne comme une table de hachage (java.util.Map) dont les valeurs sont des JsonObject, JsonArray (qui fonctionnent comme des listes (hava.util.List)), des JsonString ou des JsonNumber.

  1. Écrire un code qui affiche tous les items du tableau dont la clé est "items".
  2. Modifier votre code pour afficher juste les valeurs des champs "id" et "name" de tous les items.
  3. À quoi sert la méthode JSonArray.getValuesAs? Comment peut-on l'utiliser ici ?

Exercice 3 - Json parsing en mode Stream Model [à la maison]

On cherche à afficher la valeur des champs id et name mais en utilisant l'API de streaming de Json parsing.
Enfin, on chronométrera les temps d'exécution pour vérifier qu'utiliser l'API de streaming est plus rapide.

La création d'un parseur 'stream' se fait en utilisant un JsonParser
      JsonParser parser = Json.createParser(reader);
     
Un parseur possède les méthodes hasNext et next qui fonctionnent de la même façon qu'un itérateur et renvoient les évènements associés à la structure du document.
La méthode parser.getString() permet d'obtenir sous forme de chaine de caractères la valeur associée à un évènement.

  1. Écrire un code qui affiche l'ensemble des évènements liés au parsing de la structure du document.
  2. Modifier votre code pour n'afficher que la valeur des champs id et name de n'importe quel objet.
    L'astuce consiste, lors d'un évènement KEY_NAME, à stocker dans une variable locale la valeur de la clé que l'on a vue (id ou name). Ensuite, lors de l'évènement VALUE_NUMBER ou VALUE_STRING correspondant, on affiche la valeur correspondante.
  3. Maintenant, seules les clés id et name de item nous intéressent.
    Si on ne regarde que les évènements d'entrée dans un objet (START_OBJECT) et de sortie d'un objet (END_OBJECT), les objets item sont les seuls ayant une profondeur de 2. Il est donc facile de ne récupérer id et name que lorsque la profondeur est 2.
    Écrire le code permettant d'obtenir le même affichage que celui de l'exercice précédent.
  4. Enfin, utiliser System.nanoTime pour vérifier que le parsing avec l'API de streaming est plus rapide que le parsing avec l'Object Model.