Décodage JSON en brindille
est-il possible de décoder JSON en brindille? Google ne semble pas produire quoi que ce soit à ce sujet. Le décodage de JSON dans Twig n'a pas de sens?
j'essaie d'accéder à 2 propriétés entity sur le type de champ entity D'un Symfony2 ( Type De Champ De L'Entité).
une fois à venir à travers les 2 précédentes AINSI en question ( Symfony2 type de champ entité alternatives à "propriété"ou" _ _ toString ()"? et Symfony 2 Créer un champ de formulaire entité avec 2 propriétés) qui suggérait d'ajouter une méthode supplémentaire à une entité pour récupérer une chaîne personnalisée plutôt qu'un attribut d'entité, j'ai pensé (et je l'ai fait) retourner une chaîne JSON représentant une instance d'objet.
quelque part dans la classe d'entité:
/**
* Return a JSON string representing this class.
*/
public function getJson()
{
return json_encode(get_object_vars($this));
}
Et dans la forme (quelque chose comme):
$builder->add('categories', 'entity', array (
...
'property' => 'json',
...
));
après, j'espérais json_decode
il en brindille...
{% for category in form.categories %}
{# json_decode() part is imaginary #}
{% set obj = category.vars.label|json_decode() %}
{% endfor %}
7 réponses
c'est facile si vous étendre la brindille.
tout d'Abord, créez une classe qui contiendra l'extension:
<?php
namespace Acme\DemoBundle\Twig\Extension;
use Symfony\Component\DependencyInjection\ContainerInterface;
use \Twig_Extension;
class VarsExtension extends Twig_Extension
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function getName()
{
return 'some.extension';
}
public function getFilters() {
return array(
'json_decode' => new \Twig_Filter_Method($this, 'jsonDecode'),
);
}
public function jsonDecode($str) {
return json_decode($str);
}
}
alors, Inscrivez cette classe dans vos Services.fichier xml:
<service id="some_id" class="Acme\DemoBundle\Twig\Extension\VarsExtension">
<tag name="twig.extension" />
<argument type="service" id="service_container" />
</service>
Puis, l'utiliser sur votre templates twig:
{% set obj = form_label(category) | json_decode %}
j'ai trouvé un moyen d'atteindre mon JSON et j'ai pensé le partager ici au cas où il serait utile à quelqu'un d'autre.
donc dans mon cas j'ai peut-être 10 enregistrements (layouts) retournés à partir d'une base de données mysql et chaque ligne a un champ appelé propriétés qui est une chaîne json. Ainsi, je peux facilement extraire les enregistrements et les envoyer au modèle comme ceci:
echo $twig->render('template.html.twig', array(
"layouts" => $layouts,
));
jusqu'à présent si bon, cependant quand je fais mon {% pour la mise en page dans les layouts %} dans la brindille il n'y a aucun moyen d'obtenir les propriétés les éléments de champ car ils sont toujours une chaîne json.
donc juste avant de passer $layouts au modèle de brindille j'ai fait ce qui suit:
foreach($layouts as $i => $v)
{
$layouts[$i]->decoded = json_decode($v->getProperties());
}
en faisant cela J'ai créé une variable à la volée dans mon objet appelé 'décodé' qui contient l'objet décodé par json.
donc maintenant dans mon modèle je peux accéder à mes articles json par {{layout.décoder.quoi qu' }}
cela pourrait être un peu hacky et pas à tout le monde idée d'une bonne solution. Je travaille bien pour moi, très peu de frais généraux et signifie que je n'ai pas à jouer avec extension de brindille comme Im faire le travail avant qu'il arrive au modèle.
autres pour tous les ci-dessus.
Et je ne sais pas si c'est la solution optimale, mais il .
1) Créer un fonction d'assistance et s'inscrire cette fonction.
<?php
function twig_json_decode($json)
{
return json_decode($json, true);
}
2) Utilisez cette fonction dans votre fichier twig.
{% set res = twig_json_decode(json) %}
# above will return an array which can be iterated
{% for r is res %}
{{ r }}
{% endfor %}
Code mis à jour pour Symfony2.8 or Symfony3:
<?php
namespace Acme\DemoBundle\Twig\Extension;
use Symfony\Component\DependencyInjection\ContainerInterface;
use \Twig_Extension;
class VarsExtension extends Twig_Extension
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function getName()
{
return 'some.extension';
}
// Note: If you want to use it as {{ json_decode(var) }} instead of
// {{ var|json_decode }} please use getFunctions() and
// new \Twig_SimpleFunction('json_decode', 'json_decode')
public function getFilters() {
return [
// Note that we map php json_decode function to
// extension filter of the same name
new \Twig_SimpleFilter('json_decode', 'json_decode'),
];
}
}
dans mon cas j'ai un JsonArray dans mon Entity puis j'ai ajouté dans mon Entity une méthode
<?php
namespace ACME\DefaultBundle\Entity;
/*...*/
public function getDecodedPath()
{
return json_decode($this->path);
}
C'est une vieille question mais j'ajoute ma solution pour le dossier... Il suffit d'étendre la brindille avec une fonction simple:
// Return a string of separated values from a JSON string
// Can optionally specify a separator. If none provided, ", " is used.
$function = new Twig_SimpleFunction('json_to_list', function($json, $separator = ", ")
{
$result = "";
$array = json_decode($json, true);
foreach ($array as $item)
{
if ($result != "") { $result .= $separator; }
$result .= $item;
}
return $result;
});
$twig->addFunction($function);
Utilisation:
définir a_json_variable à la chaîne '["1","2","3","4","5"]' avant d'appeler le Rameau de rendu.
modèle de brindille:
The values are: {{ json_to_list(a_json_variable) }}
produira
The values are: 1, 2, 3, 4, 5
pour Symfony 3.1, comme le doc officiel dit, il est une aide à cet effet: return $this->json()
:
/**
* @Route("/", name="homepage")
* @Method({"GET","POST"})
*/
public function indexAction()
{
$person = new Person();
$form = $this->createForm(PersonType::class, $person,[
'action'=>$this->generateUrl('homepage'),
'method'=>'POST'
]);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
return $this->json([
'name'=>$person->getName(),
'age'=>$person->getAge()
]);
}
return $this->render('default/index.html.twig',['form'=>$form->createView()]);
}
La sortie est de la forme:
{"name":"john","age":39}