Je me promenais donc dans php.net pour obtenir des informations sur la sérialisation des objets PHP en JSON, lorsque je suis tombé sur la nouvelle interface JsonSerializable . C'est seulement PHP> = 5.4 cependant, et j'exécute dans un environnement 5.3.x.
Comment ce type de fonctionnalité est-il réalisé? PHP <5.4 ?
Je n'ai pas encore beaucoup travaillé avec JSON, mais j'essaie de prendre en charge une couche API dans une application et de vider l'objet de données ( qui serait autrement envoyé à la vue ) dans JSON serait parfait.
Si j'essaye de sérialiser l'objet directement, il renvoie une chaîne JSON vide; qui est parce que je suppose json_encode()
ne sait pas ce que diable faire avec l'objet. Dois-je réduire récursivement l'objet dans un tableau, puis encoder cela ?
Exemple
$data = new Mf_Data();
$data->foo->bar['hello'] = 'world';
echo json_encode($data)
produit un objet vide:
{}
var_dump($data)
cependant, fonctionne comme prévu:
object(Mf_Data)#1 (5) {
["_values":"Mf_Data":private]=>
array(0) {
}
["_children":"Mf_Data":private]=>
array(1) {
[0]=>
array(1) {
["foo"]=>
object(Mf_Data)#2 (5) {
["_values":"Mf_Data":private]=>
array(0) {
}
["_children":"Mf_Data":private]=>
array(1) {
[0]=>
array(1) {
["bar"]=>
object(Mf_Data)#3 (5) {
["_values":"Mf_Data":private]=>
array(1) {
[0]=>
array(1) {
["hello"]=>
string(5) "world"
}
}
["_children":"Mf_Data":private]=>
array(0) {
}
["_parent":"Mf_Data":private]=>
*RECURSION*
["_key":"Mf_Data":private]=>
string(3) "bar"
["_index":"Mf_Data":private]=>
int(0)
}
}
}
["_parent":"Mf_Data":private]=>
*RECURSION*
["_key":"Mf_Data":private]=>
string(3) "foo"
["_index":"Mf_Data":private]=>
int(0)
}
}
}
["_parent":"Mf_Data":private]=>
NULL
["_key":"Mf_Data":private]=>
NULL
["_index":"Mf_Data":private]=>
int(0)
}
Addenda
1)
toArray()
Voici donc la fonction que j'ai conçue pour la Mf_Data
classe:
public function toArray()
{
$array = (array) $this;
array_walk_recursive($array, function (&$property) {
if ($property instanceof Mf_Data) {
$property = $property->toArray();
}
});
return $array;
}
Cependant, comme les Mf_Data
objets ont également une référence à leur objet parent ( contenant ), cela échoue avec la récursivité. Fonctionne comme un charme quand je supprime la _parent
référence.
2)
Juste pour faire un suivi, la fonction finale pour transformer un objet complexe de nœud d'arbre avec lequel je suis allé était:
// class name - Mf_Data
// exlcuded properties - $_parent, $_index
public function toArray()
{
$array = get_object_vars($this);
unset($array['_parent'], $array['_index']);
array_walk_recursive($array, function (&$property) {
if (is_object($property) && method_exists($property, 'toArray')) {
$property = $property->toArray();
}
});
return $array;
}
3)
Je fais un suivi à nouveau, avec une mise en œuvre un peu plus claire. L'utilisation d'interfaces pour une instanceof
vérification semble beaucoup plus propre que method_exists()
( cependant l' method_exists()
héritage / l'implémentation croisée ).
L'utilisation unset()
semblait aussi un peu compliquée, et il semble que la logique devrait être refactorisée dans une autre méthode. Toutefois, cette mise en œuvre ne copier le tableau de la propriété ( en raison dearray_diff_key
), donc quelque chose à considérer.
interface ToMapInterface
{
function toMap();
function getToMapProperties();
}
class Node implements ToMapInterface
{
private $index;
private $parent;
private $values = array();
public function toMap()
{
$array = $this->getToMapProperties();
array_walk_recursive($array, function (&$value) {
if ($value instanceof ToMapInterface) {
$value = $value->toMap();
}
});
return $array;
}
public function getToMapProperties()
{
return array_diff_key(get_object_vars($this), array_flip(array(
'index', 'parent'
)));
}
}
la source
JsonSerializable
Réponses:
edit : nous sommes actuellement le 24/09/2016, et PHP 5.4 a été publié le 01/03/2012, et le support a pris fin le 01/09/2015. Pourtant, cette réponse semble gagner des votes positifs. Si vous utilisez toujours PHP <5.4, vous créez un risque de sécurité et mettez fin à votre projet . Si vous n'avez aucune raison impérieuse de rester à <5.4, ou même d'utiliser déjà la version> = 5.4, n'utilisez pas cette réponse , et utilisez simplement PHP> = 5.4 (ou, vous savez, une version récente) et implémentez l'interface JsonSerializable
Vous définiriez une fonction, par exemple nommée
getJsonData();
, qui renverrait soit un tableau, unstdClass
objet, soit un autre objet avec des paramètres visibles plutôt que des paramètres privés / protégés, et faire unjson_encode($data->getJsonData());
. En gros, implémentez la fonction de 5.4, mais appelez-la à la main.Quelque chose comme ça fonctionnerait, comme
get_object_vars()
on l'appelle depuis l'intérieur de la classe, en ayant accès aux variables privées / protégées:la source
stdClass
? Je pense dans la direction de Reflection , mais sinon, je vais juste trouver quelque chose pour l'exécuter de manière récursive.getJsonData()
fonction, vous pouvez simplement appelerget_object_vars()
et parcourir ce résultat en recherchant plus d'objets._parent
propriété pour que l'arborescence puisse être parcourue jusqu'à la racine. Voir ma modification pour une mise à jour; peut-être devrais-je poser une autre question car cette question est maintenant extraite de mon original.unset($array['_parent']);
avant la marche devrait faire l'affaire.$parent
tant que données utilisateur àarray_walk_recursive()
. Le simple est beau! De plus, c'est à$array["\0class\0property"]
cause de la pollution de zéro octet parce que j'utilisais la diffusion. Je pense que je vais passer àget_object_vars()
.Dans les cas les plus simples, l'indication de type devrait fonctionner:
la source
json_encode()
ne codera que les variables membres publiques. donc si vous souhaitez inclure le privé une fois que vous devez le faire vous-même (comme les autres l'ont suggéré)la source
Le code suivant fait le travail en utilisant la réflexion. Il suppose que vous avez des getters pour les propriétés que vous souhaitez sérialiser
la source
Implémentez simplement une interface fournie par PHP JsonSerializable .
la source
Étant donné que votre type d'objet est personnalisé, j'aurais tendance à être d'accord avec votre solution - décomposez-la en segments plus petits à l'aide d'une méthode de codage (comme JSON ou sérialisation du contenu), et à l'autre extrémité, j'ai le code correspondant pour reconstruire l'objet.
la source
Ma version:
La mise en oeuvre:
JsonUtils: GitHub
la source
Essayez d'utiliser ceci, cela a bien fonctionné pour moi.
la source
Remplacez vos types de variables
private
parpublic
C'est simple et plus lisible.
Par exemple
Ca ne fonctionne pas;
Ça fonctionne;
la source
J'ai créé une belle classe d'assistance qui convertit un objet avec des méthodes get en un tableau. Il ne repose pas sur des propriétés, juste des méthodes.
J'ai donc l'objet de révision suivant qui contient deux méthodes:
La revue
Commentaire
Le script que j'ai écrit le transformera en un tableau avec des propriétés qui ressemblent à ceci:
Source: PHP Serializer qui convertit un objet en un tableau pouvant être encodé en JSON.
Tout ce que vous avez à faire est d'enrouler json_encode autour de la sortie.
Quelques informations sur le script:
la source
J'ai passé quelques heures sur le même problème. Mon objet à convertir en contient beaucoup d'autres dont je ne suis pas censé toucher aux définitions (API), j'ai donc trouvé une solution qui pourrait être lente je suppose, mais je l'utilise à des fins de développement.
Celui-ci convertit n'importe quel objet en tableau
Cela convertit n'importe quel objet en stdClass
la source
unlink($thisAnswer);
inline php strings
,eval
,shell_exec(php)
... cc-combo.