Dans ce tutoriel, nous allons aborder le parsing de fichiers JSON (JavaScript Object Notation) à l’aide de la bibliothèque Jackson.


Qu’est-ce que JSON ?

JSON est un format léger d’échange de données. Il est facile à écrire et lire, facilement analysable. C’est un format totalement indépendant de tout langage. Ce qui en fait un langage d’échange de données idéal.

Il se base sur deux structures :

  • Une collection de couple “Nom / Valeur”
  • Une liste de valeurs ordonnées

Pourquoi Jackson ?

Pour cet article, nous allons utiliser la bibliothèque Jackson. Vous allez surement vous demandez “Pourquoi Jackson ?”. Tout simplement parce qu’à mon avis c’est la meilleur bibliothèque de parsing JSON en général et aussi sous Android. Ce benchmark vous aidera à être convaincu.
Jackson est une bibliothèque :

  • de Streaming (Lecture / Ecriture)
  • Rapide
  • Puissante
  • Possédant aucune dépendance
  • Open Source
  • Configurable à souhait.

Vous pouvez obtenir plus d’informations sur le site officiel de jackson.

Mise en place du projet

Pour notre projet, nous allons avoir besoin d’un exemple de fichier JSON. Voici notre petit exemple qui sera disponible sur : users.json

{
    "Users": [
        {
            "firstname": "Nazim",
            "lastname": "Benbourahla",
            "login": "n_benbourahla",
            "twitter": "@n_benbourahla",
            "web": ""
        },
        {
            "firstname": "Tutos",
            "lastname": "android",
            "login": "Tutos-android",
            "twitter": "",
            "web": "www.tutos-android.com"
        }
    ]
}

Nous allons créer un projet Android avec les caractéristiques suivantes :

  • Nom du projet : TutosAndroidJsonParser
  • Version du SDK : 2.2
  • Nom de l’application : JSON Parser
  • Package : com.tutos.android.json
  • Activité : JsonParserMainActivity

Nous allons créer un dossier lib à la racine de notre projet dans lequel nous allons mettre les jars de Jackson qui sont disponible ici.
Sans oublier de rajouter les jars au Build Path du projet.

Pour commencer nous allons créer notre vue, qui sera composé d’un bouton et d’un texte pour afficher le JSON.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

<Button 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:text="Parser le fichier JSON"
    android:id="@+id/startParsing"
/>

<TextView  
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
   	android:id="@+id/jsonDisplay"
    />
</LinearLayout>

Puis nous allons créer nos modèles, correspondant à notre objet User passer dans le JSON.
Voici notre classe User

package com.tutos.android.json.model;

public class User {
    private String firstname;
    private String lastname;
    private String login;
    private String twitter;
    private String web;
    
    public User() {
	super();
	this.firstname = "";
	this.lastname = "";
	this.login = "";
	this.twitter = "";
	this.web = "";
    }
    
    public User(String firstName, String lastName, String login, 
                String twitter, String web) {
	super();
	this.firstname = firstName;
	this.lastname = lastName;
	this.login = login;
	this.twitter = twitter;
	this.web = web;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstName) {
        this.firstname = firstName;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastName) {
        this.lastname = lastName;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getTwitter() {
        return twitter;
    }

    public void setTwitter(String twitter) {
        this.twitter = twitter;
    }

    public String getWeb() {
        return web;
    }

    public void setWeb(String web) {
        this.web = web;
    }

}

Puis la liste des utilisateurs, qui correspond tout simplement à une HashMap de correspondance

package com.tutos.android.json.model;

import java.util.ArrayList;
import java.util.HashMap;

public class Users extends HashMap<String, ArrayList<User>> {

    private static final long serialVersionUID = 1L;

}

Une fois notre modèle prêt, nous allons créer une classe qu’on nommera UserController. Cette classe s’occupera de télécharger, parser notre JSON

package com.tutos.android.json.model;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.ObjectMapper;

import android.os.Environment;

public class UsersController {

    private static final String DL_URL = "http://www.tutos-android.com/JSON/users.json";

    private ObjectMapper objectMapper = null;
    private JsonFactory jsonFactory = null;
    private JsonParser jp = null;
    private ArrayList<User> userList = null;
    private Users users = null;
    private File jsonOutputFile;
    private File jsonFile;

    public UsersController() {
	objectMapper = new ObjectMapper();
	jsonFactory = new JsonFactory();
    }

    public void init() {
	downloadJsonFile();
	try {
	    jp = jsonFactory.createJsonParser(jsonFile);
	    users = objectMapper.readValue(jp, Users.class);
	    userList = users.get("Users");
	} catch (JsonParseException e) {
	    e.printStackTrace();
	} catch (IOException e) {
	    e.printStackTrace();
	}
    }
    
    private void downloadJsonFile() {
	try {
	    createFileAndDirectory();
	    URL url = new URL(UsersController.DL_URL);
	    HttpURLConnection urlConnection;
	    urlConnection = (HttpURLConnection) url.openConnection();
	    urlConnection.setRequestMethod("GET");
	    urlConnection.setDoOutput(true);
	    urlConnection.connect();
	    FileOutputStream fileOutput = new FileOutputStream(jsonFile);
	    InputStream inputStream = urlConnection.getInputStream();
	    byte[] buffer = new byte[1024];
	    int bufferLength = 0;
	    while ((bufferLength = inputStream.read(buffer)) > 0) {
		fileOutput.write(buffer, 0, bufferLength);
	    }
	    fileOutput.close();
	} catch (MalformedURLException e) {
	    e.printStackTrace();
	} catch (IOException e) {
	    e.printStackTrace();
	}
    }
    
    private void createFileAndDirectory() throws FileNotFoundException {
	final String extStorageDirectory = Environment
		.getExternalStorageDirectory().toString();
	final String meteoDirectory_path = extStorageDirectory + "/tutos-android";
	jsonOutputFile = new File(meteoDirectory_path, "/");
	if (jsonOutputFile.exists() == false)
	    jsonOutputFile.mkdirs();
	jsonFile = new File(jsonOutputFile, "users.json");
    }

    public ArrayList<User> findAll() {
	return userList;
    }

    public User findById(int id) {
	return userList.get(id);
    }

}

Cette classe s’occupera de :

  • Créer un dossier “tutos-android” sur le téléphone, puis un fichier users.json (createFileAndDirectory)
  • Ouvrir une connexion avec le serveur pour lire le contenu du JSON et le recopier localement (downloadJsonFile)
  • Initialise notre parseur, à l’aide du fichier JSON local
     jp = jsonFactory.createJsonParser(jsonFile);
    
  • Lecture des valeurs portant la balise “Users
    users = objectMapper.readValue(jp, Users.class);
  • Récupération de la liste des utilisateurs

    userList = users.get("Users");

Comme vous venez de le remarquer, parser un fichier JSON est très simple et rapide.

Pour finir, nous allons implémenter notre activité pour :

  • Télécharger notre fichier JSON
  • Afficher le résultat dans le TextView
package com.tutos.android.json;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.tutos.android.json.model.User;
import com.tutos.android.json.model.UsersController;

public class JsonParserMainActivity extends Activity {
    private UsersController usersController;
    private TextView displayJson;

    @Override
    public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);
	usersController = new UsersController();

	displayJson = (TextView) findViewById(R.id.jsonDisplay);

	Button startParsing = (Button) findViewById(R.id.startParsing);
	startParsing.setOnClickListener(new OnClickListener() {
	    @Override
	    public void onClick(View view) {
		gettingJson();
	    }
	});
    }

    final void gettingJson() {
	final Thread checkUpdate = new Thread() {
	    public void run() {
		usersController.init();
		final StringBuilder str = new StringBuilder("user : ");
		for (User u : usersController.findAll()) {
		    str.append("\n").append("first name : ").append(u.getFirstname());
		    str.append("\n").append("last name : ").append(u.getLastname());
		    str.append("\n").append("login : ").append(u.getLogin());
		    str.append("\n").append("twitter : ").append(u.getTwitter());
		    str.append("\n").append("Web : ").append(u.getWeb());
		}
		runOnUiThread(new Runnable() {
		        @Override
		        public void run() {
		            displayJson.setText(str.toString());
		        }
		    });
		
	    }
	};
	checkUpdate.start();
    }

}

Ce qui vous donnera le résultat suivant :

Pour finir je vous fournit le zip contenant le projet, vous pouvez le télécharger ici

Conclusion

Ce tutoriel s’arrête ici en espérant qu’il vous a aidé a comprendre comment fonctionne le parsing JSON sous Android, l’utilité de la bibliothèque Jackson ainsi que l’avantage que peux procurer JSON sur d’autres formats disponibles comme XML par exemple.

Categories: Tutoriels

42 Responses so far.


  1. Same dit :

    Merci pour cette précision darkhi!
    Du coup je me demande bien, si Json.org ne suffit pas largement pour des projets sur android?

    • darkhi dit :

      Oui, Json.org est très bien et très léger.
      Avant Gson, on utilisait une APi maison basée sur org.json + réflexion java pour gérer la couche d’intégration, car json ne gère pas le mapping vers un modèle arbitraire.
      Donc si tu as besoin d’opérer une intégration automatique d’un service REST vers ton modèle métier, avec org.json, tu dois encore ajouter une couche DAO pour remapper le modèle arobrescent de json.org.
      Sinon GSon le gère très bien, avec une perte de performance très minime par rapport à Json.org, mais avec une lisibilité accrue, et une limitation des sources de bug dans ta couche intégration.

  2. darkhi dit :

    Bonjour.
    Je sais que ce tuto date de 2011, donc ce que je vais dire n’est pas du fait de l’auteur.
    Sur notre application, on a un modèle objet assez profond (lourd), et Jackson se révèle très, très lent sur mobile (y compris sur les tablettes récentes). En fait, il s’étale en mémoire, bouffe du CPU pour trouver ses mappers à chaque objet qu’il doit mapper, et instancie des objets à foison, déclenchant régulièrement des GCs.
    Jackson a beau être une excellente API sur serveur, il est mauvais sur environnement à ressources limitées.
    Je conseille d’utiliser à la place google GSON (https://sites.google.com/site/gson/Home ), qui chez nous s’exécute en environ 7~8 fois moins de temps (sans déconner), prend moins de place en mémoire, et de surcroit est vraiment trivial à l’utilisation.

Leave a Reply


Notifiez-moi des commentaires à venir via email. Vous pouvez aussi vous abonner sans commenter.