Génerer un fichier JSON rapidement et facilement avec Struts 2.1

struts2+json Nous continuons sur le thème des applications web avec le framework Struts 2. Pour rappel, Struts 2 permet de construire facilement des applications web, avec une architecture Model-View-Controller et ainsi améliorer la maintenance de son code. Nous allons voir ici comment générer un fichier JSON avec Struts2. JSON (JavaScript Object Notation) est un format de données similaire au XML, mais orienté pour l’échange de données avec du JavaScript: des frameworks JavasScript tel que Dojo ou jQuery implémentent des fonctionnalités pouvant manipuler de telle structures de données.

JSON (JavaScript Object Notation) est un format de données textuel, générique, dérivé de la notation des objets du langage ECMAScript. Il permet de représenter de l’information structurée. Créé par Douglas Crockford, il est décrit par la RFC 4627 de l’IETF.
Bien qu’utilisant une notation JavaScript, JSON est indépendant du langage de programmation. Le site officiel présente (en août 2005) des solutions d’intégration de JSON pour 33 langages de programmation. Il sert à faire communiquer des applications dans un environnement hétérogène. Il est notamment utilisé comme langage de transport de données par AJAX et les services Web. D’autres solutions sont possibles comme XML. Le type MIME application/json est utilisé pour le transmettre par le protocole HTTP.
Vis-à-vis de JavaScript, un document JSON représente un objet, d’où son nom. Il est donc potentiellement plus facile à interpréter qu’un XML qui imposera le recours à des techniques, souvent plus lourdes qu’un accès direct, telle que le parcours hiérarchique de l’arbre DOM représenté par le document entier.
Source: Wikipedia

A quoi ca ressemble du JSON

Considérons que nous avons, la structure de données suivante et que nous souhaitons sérialisé JsonTestAction:

UML Json Struts

Ce diagramme UML donnerait ceci en Java:

/**
 * @author Eric Vialle
 */
public class JsonTestAction {
 
	/** Champ name sera affiché dans le fichier JSON */
	private String				name;
 
	/** Champ date sera affiché dans le fichier JSON */
	private Date				date;
 
	/**
	 * Liste de MyAccountBean pouvant être sérialisée.
	 */
	private List	accountList;
 
	/**
	 * MyAccountBean peut être définie dans cette classe ou ailleurs.
	 */
	public class MyAccountBean {
 
		private String	login;
 
		private String	password;
 
		public void setLogin(String login) {
			this.login = login;
		}
 
		public String getLogin() {
			return login;
		}
 
		public void setPassword(String password) {
			this.password = password;
		}
 
		public String getPassword() {
			return password;
		}
	}
 
	/**
	 * Ce champ est un service Spring. Nous ne souhaitons pas
	 * afficher/sérialiser ce champ dans le fichier JSON.
	 */
	private AccountService	accountService;
 
	public void setAccountList(List accountList) {
		this.accountList = accountList;
	}
 
	public List getAccountList() {
		return accountList;
	}
 
	public void setDate(Date date) {
		this.date = date;
	}
 
	public Date getDate() {
		return date;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	public String getName() {
		return name;
	}
}

Avec des données, nous aurions ceci:

L’implémenter dans Struts

La génération d’un fichier Struts se fait par une Action, suite à une configuration pour dire:

  1. que l’application web supporte les sorties JSON
  2. que le package d’Action supporte le JSON
  3. que l’Action génére une sortie JSON et non pas une sortie HTML classique

Installer le support de JSON dans l’Application Struts

Le support de JSON se fait via l’ajout d’un plugin

Depuis la version 2.1.8 de Struts, le plugin JSON de Struts (prenant la forme du JAR dénommé struts2-json-plugin.jar) est inclus par défaut dans la distribution de Struts. Pour rappel, l’ajout d’un plugin se fait en ajoutant simplement le JAR dans le classpath.

Ajoutez le support JSON à un Package

Si vous n’utilisez pas les Interceptor, vous Il faut aussi vérifier que l’action qui se chargera de générer votre fichier JSON aura comme Interceptor jSonValidation. L’Interceptor par défaut ne le contient pas.
L’interceptor JSON est référencé par:

<interceptor-ref name="jsonValidation"/>

Vous pouvez utiliser déclarer cet Interceptor ainsi dans votre struts-config.xml:

<package name="mypackage" namespace="mynamespace">
    <interceptors>
       <!-- On ajoute jsonValidation à la stack Interceptor par défaut -->
       <interceptor-stack name="defaultJsonStack">
          <interceptor-ref name="defaultStack" />
          <interceptor-ref name=<span>"jsonValidation"/>
      </interceptor-stack>
    </interceptors>
    <default-interceptor-ref name="defaultJsonStack" />
   <!-- Déclarer ici vos actions Struts -->
</package>

Sans toucher aux Interceptors, il est aussi possible d’activer la gestion de json dans un package en étendant celui-ci par le package json-default

<package name="mypackage" namespace="mynamespace" extends="json-default">
    <!-- Déclarer ici vos actions Struts-->
 </package>

Désigner une Action générant une sortie JSON

Pour générer une sortie JSON, l’Action va être en faite sérialisée. Tous les champs accessibles par un getter et un setter de cette Action seront mis dans la sortie JSON. Vous utiliserez la méthode execute() afin d’initialiser tous les champs de cette Action.

/**
 * @author Eric Vialle
 */
public class JsonTestAction extends ActionSupport {
 
	/** Methode executée par défaut, qui va remplir le contenu de chaque champ. */
	public String execute() {
 
		setName("MonNom");
		setDate(new Date());
 
		// ...... you may init as well the List of AccountBean
 
		return SUCCESS;
	}
 
	/** Champ name sera affiché dans le fichier JSON */
	private String name;
 
	/** Champ date sera affiché dans le fichier JSON */
	private Date date;
 
	/**
	 * Liste de MyAccountBean pouvant être sérialisée.
	 */
	private List accountList;
 
	/**
	 * MyAccountBean peut être définie dans cette classe ou ailleurs.
	 */
	public class MyAccountBean {
 
		private String login;
 
		private String password;
 
		public void setLogin(String login) {
			this.login = login;
		}
 
		public String getLogin() {
			return login;
		}
 
		public void setPassword(String password) {
			this.password = password;
		}
 
		public String getPassword() {
			return password;
		}
	}
 
	/**
	 * Ce champ est un service Spring. Nous ne souhaitons pas
	 * afficher/sérialiser ce champ dans le fichier JSON.
	 */
	private AccountService accountService;
 
	public void setAccountList(List accountList) {
		this.accountList = accountList;
	}
 
	public List getAccountList() {
		return accountList;
	}
 
	public void setDate(Date date) {
		this.date = date;
	}
 
	public Date getDate() {
		return date;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	public String getName() {
		return name;
	}
}

Dans votre fichier struts-config.xml, vous pourrez déclarer votre Action ainsi dans un package ou JSON a été déclaré:

<action name="JsonTest" class="JsonTestAction">
    <result type="json"/>
</action>

La sortie générée sera de la forme:

{
	"name" : "MonNom"
	"date" : "17-03-2009 15:10:03"
}

Exclure certains champs du fichier JSON

Vous pouvez exclure la sérialisation de certains champs en modifiant la déclaration de l’Action dans struts-config.xml,

<action name="JsonTest" class="JsonTestAction">
  <result type="json">
    <param name="excludeProperties">
      date,
      nom
    </param>
  </result>
</action>

Renommer certains champs du fichier JSON

Dans le cas suivant, nous allons renommé le champ « name » par « newName » dans le fichier JSON. Les getters et setters sont inchangés:

	/** Champ name sera affiché dans le fichier JSON */
	@JSON (name= "newName" )
	private String				name;