8791 sujets

Développement web côté serveur, CMS

salut tout le monde,

je bute en ce moment sur un problème de désérialisation d'objets par json..
Je m'explique : Smiley smile
je voudrais afficher une liste d'utilisateurs qui ont enregistré leur nom et leur age dans un formulaire, et cela par ajax et dans la même page.

A chaque saisie de données dans le formulaire, je récupére ces données, les encode par json les passe par un appel json à un fichier qui les traite, en créant un objet à partir de ces données.
Ce script sérialise alors cet objet, puis stocke cet objet dans un tableau, et stocke ce tableau dans une variable session. Enfin j'encode ce tableau pour le renvoyer à la fonction appelante json du formulaire...Ooouuuf !!!

Le problème, c'est que je n'arrive plus à traiter ce tableau une fois revenu dans la fonction success de mon $.post(..)..

Voici le code d'envoi de mes données par ajax :


$(document).ready(function() {
.....
 $("#formconvert").validate({
.....
  submitHandler: function(form) {
        //show the loading sign  
        $('#loading').show();
        var user = new Object();      
        // Retrieve the title and ISBN
        user.nom = $('#nom').val();
        user.age = $('#age').val();
        // Use the jquery-json plugin to convert the form data to JSON
        var userJSON = $.toJSON(user);   

        $.post(
          'controller.php',
          {user: userJSON, q: "traiter"},
          function success(data) {

         //   $('#resultat').empty().append(data.length);     
            $('#loading').hide();        
          }                             
        ,"json");
      } 


Firebug me renvoie dans la requete post la sortie suivante :
q traiter
user {"nom":"carcy","age":"12121"}
Source
user=%7B%22nom%22%3A%22carcy%22%2C%22age%22%3A%2212121%22%7D&q=traiter
jusque-la, tout va bien !

voici mon code du traitement de mes données formulaire :


$user_form = json_decode($_POST['user'], true);
        $array_users = array ();
        
        if ( (preg_match ("#^[\w]+$#",$user_form['nom']) ) && 
           (preg_match ("#^[\d]+$#",$user_form['age'])) ) {
              
          $user = new class_user($user_form['nom'],$user_form['age']);
          $array_users = (isset($_SESSION['users'])) ? $_SESSION['users'] : array();    
          $array_users[] = serialize($user);
          $_SESSION['users'] = $array_users;
		    
          // encode et renvoie la valeur par json
          echo json_encode($array_users);
... }


A ce niveau-là, firebug m'affiche ceci :
["O:10:\"class_user\":2:{s:16:\"\u0000class_user\u0000_nom\";s:5:\"carcy\";s:16:\"\u0000class_user\u0000_age\";s:5:\"12121\";}"]
soit mon tableau encodé d'objet sérialisés...

Je n'arrive plus ensuite à récupérer les données de ce tableau, soit chaque objet le constituant, donc à désencoder le tableau passé en paramètre (ici data, qui récupère donc le json_encode($array_users); de ma fonction de traitement), puis à désérialiser les objets de ce tableau..

Quelqu'un aurait-il une idée du process de désencodage json et de désérialisation d'un tableau d'objets sérialisés ? là, je suis cplt en panne, j'avoue..

merci d'avance à tous Smiley cligne
Modifié par ishmar (27 Mar 2010 - 11:51)
Pourquoi utiliser json_encode et serialize ? Utiliser uniquement json_encode ne suffit pas ?
Tout dépend de ce que tu souhaites faire, et surtout par qui tu souhaites faire lire tes objets. Imbriquer du json (qui est une forme de sérialisation) et de la sérialisation native php me paraît bien compliqué.
Si tu n'exploites ton objet que coté php, pourquoi ne pas sérialiser directement le tableau ? Ou alors encoder tout en json, quitte à réinstancier tes objets après ?

Le souci que tu rencontres vient je pense de l'encodage. Si tu renvoies une sérialisation d'objet PHP, je pense qu'un petit passage par un base64_encode résoudra le problème. Mais tout dépend du besoin final...
yep, je n'exploite l'objet que du côté php, du côté template, je veux simplement la liste de mes users enregistrés de façon à les afficher rapidement dans une div.
Qu'appelles tu 'Sérialiser directement le tableau' ?
pou 'encoder tout en json' ?

On peut faire ceci :

echo json_encode($array_users);


sans passer par l'étape intermédiaire :
$array_users[] = serialize($user);
?

merci !
c'est possible de faire ça ?
Pour encoder tout en json, il te faudra fournir des méthodes d'export vers un tableau associatif dans ta classe class_user (voir les commentaires dans la doc).

Si tu ne veux pas t'embêter, il "suffit" de faire cela :

echo base64_encode(serialize($array_users));

Que tu récupères ensuite via

$array_users = unserialize(base64_decode(...));
ok, merci, je vais regarder en detail les commentaires à ce sujet.
Mon problème, c'est comment traduire ton instruction :

$array_users = unserialize(base64_decode(...));


en code javascript dans ma fonction callback success ...comment récupérer ces objets par des instructions javascript ou jquery ?

en tout cas, merci pour le coup de main !!
Alors justement, si tu veux exploiter ces valeurs via javascript, il faut proscrire serialize de php, et partir sur la solution alternative. Implémente 2 méthodes encodeJSON et decodeJSON dans ta classe user_class (cf. doc précédemment citée), et utilise-les à la place de Smiley un serialize.
Salut,

Tu ne peux pas Smiley lol . après avoir utiliser sérialise il est difficile d'interpréter la chaine avec javascript. Donc utilise json !

Json_encode encode tous sauf les ressources, tu peux sans problème passer un objet.
Tu peux donne l'objet à la session (serialize se fera tous seul lors de la fermeture) et json pour le retourner au javascript.


          $user = new class_user($user_form['nom'],$user_form['age']);
          $_SESSION['users'][] = $user; //pas besoin de vérifier que la clée 'users' existe
          // encode et renvoie la valeur par json  
          echo json_encode($user);  


Au passage il existe l'interface Serializable pour les objets, et tu peux l'utiliser dans ton cas :


//la classe et faite un peu à larache pour l'exemple '^^
class class_user implements Serializabl
{
$nom; $age;
...
	public function serialize()
	{
		//tu peux préciser les variable à enregistrer en les mettant dans un tableau
		return json_encode($this, true);
	}
	public function unserialize($data)
	{
		foreach (json_decode($this) as $k => $v)
			$this->$k = $v;
	}
}
//en ne reprenant que le if
$user = new class_user($user_form['nom'],$user_form['age']);
$_SESSION['users'][] = $user;
echo $user->serialize();
je me disais bien que c'etait un peu compliqué de vouloir sérialiser puis encoder par json..:)

merci à tous les 2, je vais dans un premier temps virer le serialize et encoder simplement par json, puis j'essaierais l'interface Serializable.
merci pour l'aide, je commence à ramer bcq moins maintenant Smiley ravi
finalement j'ai réussi à faire fonctionner le script, en créant des methodes dans ma class_user :

    // implementation methodes encodage json
    public function jsonEncode() 
    { 
        foreach ($this as $key => $value) {
          $json->$key = $value;
        }
        return json_encode($json, true); 
    } 
    
    public function jsonDecode($data) 
    { 
        foreach (json_decode($data) as $k => $v) { 
          $this->$k = $v; 
        }                                 
    }

c indispensable, parce qu'apparemment un json_encode(objet) n'encode que les propriétés publiques de l'objet, et je me retrouvais avec un encodage vide..

dans mon controller, je fais le traitement suivant :


$user_form = json_decode($_POST['user'], true);
        
        if ( (preg_match ("#^[\w]+$#",$user_form['nom']) ) && 
           (preg_match ("#^[\d]+$#",$user_form['age'])) ) {
              
          $user = new class_user($user_form['nom'],$user_form['age']);        
          $_SESSION['users'][] = $user->jsonEncode();
        }

        echo json_encode($_SESSION['users']);


en response echo json_encode, firebug me renvoie ça :
["{\"_nom\":\"erztdfgdfgdfg\",\"_age\":\"121\"}"]

je n'ai plus qu'à bidouiller le code de ma fct success, ce qui donne ceci :


$.post(
          'controller.php',
          {user: userJSON, q: "traiter"},
          function success(data) {
            var strUser = "";  

            for (var i = 0; i < data.length; i++) {
              strUser += "<input type='checkbox' name='"+$.evalJSON(data[i])._nom+"' id='"+$.evalJSON(data[i])._nom+"'>"
						  strUser += " User : " + $.evalJSON(data[i])._nom + " - age " + $.evalJSON(data[i])._age + "<br />" ;
					  }
            
            $('#resultat').empty().append(strUser);     
            $('#loading').hide();        
          }                             
          ,"json");


un 2e appel à $.evalJSON est nécessaire pour désencoder chaque elt du tableau ,et ça marche !!!

merci à tous Smiley ravi ,
je vais essayerde refaire la mm chose avec l'implementation de serialize maintenant Smiley smile [/i][/i][/i][/i]
Modifié par ishmar (26 Mar 2010 - 17:28)