Symfony Form — JsonType
Handling Json input
Use case
Imagine given use case of sending whole JSON via form (by encoding array on Frontend) like that:
Related article: Handling Vue.js form in Symfony
The issue
Symfony form handler allows using different input types like TextType
, ArrayChoiceList
, ChoiceType
etc. while using Array
based type the result is an empty array. The only one working case is TextType
but it still yields just raw json — but that’s undesired result.
JsonType
After struggling for a while, the only working solution I’ve found is providing new input type (JsonType
) and new DataTransformer
like that:
DataTransformer
<?php
namespace App\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
/**
* Handles transforming json to array and backward
*/
class JsonTransformer implements DataTransformerInterface
{
/**
* @inheritDoc
*/
public function reverseTransform($value): mixed
{
if (empty($value)) {
return [];
}
return json_decode($value);
}
/**
* @ihneritdoc
*/
public function transform($value): mixed
{
if (empty($value)) {
return json_encode([]);
}
return json_encode($value);
}
}
JsonType
<?php
namespace App\Form\Type;
use App\Form\DataTransformer\JsonTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Serializer\SerializerInterface;
/**
* Handles json based input (for example multiselect tag)
* Will only transform the json to array (and back),
*
* If necessary, could probably accept custom options (className) which would be used to
* transform the data into given class via {@see SerializerInterface}
*/
class JsonType extends AbstractType
{
/**
* @inheritDoc
*/
public function getParent(): string
{
return TextType::class;
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->addModelTransformer(new JsonTransformer());
}
}
Summary
The end result is an array transformed from the json.