mcfedr/json-form
Symfony bundle/trait that lets controllers handle forms submitted as JSON. Use JsonControllerTrait to create and process JSON-backed forms, accepting payloads shaped like normal form fields, then validate and persist as usual.
Installation
composer require mcfedr/json-form
Add to composer.json if not auto-loaded:
"autoload": {
"psr-4": {
"App\\": "app/",
"Mcfedr\\JsonForm\\": "vendor/mcfedr/json-form/src/"
}
}
Run composer dump-autoload.
First Use Case Bind JSON data to a Symfony form in Laravel:
use Mcfedr\JsonForm\JsonFormBinder;
$jsonData = '{"name":"John","email":"[email protected]"}';
$form = $this->createForm(YourFormType::class);
$binder = new JsonFormBinder();
$form->submit($binder->bind($jsonData, $form));
Request Handling Extract JSON from incoming requests (e.g., API payloads):
$requestData = json_decode($request->getContent(), true);
$jsonString = json_encode($requestData);
Form Submission Bind JSON to a Symfony form:
$form = $this->createForm(YourFormType::class);
$form->submit($binder->bind($jsonString, $form));
Validation & Processing Check if form is valid:
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
// Process $data (e.g., save to DB)
}
use Mcfedr\JsonForm\JsonFormBinder;
class ApiController extends Controller
{
protected $binder;
public function __construct(JsonFormBinder $binder)
{
$this->binder = $binder;
}
public function store(Request $request)
{
$form = $this->createForm(YourFormType::class);
$form->submit($this->binder->bind($request->getContent(), $form));
if ($form->isValid()) {
return response()->json(['success' => true]);
}
return response()->json(['errors' => $form->getErrors()], 400);
}
}
Useful for APIs with variable schemas:
$json = '{"type":"user","name":"Alice"}';
$formType = $json['type'] === 'user' ? UserFormType::class : GuestFormType::class;
$form = $this->createForm($formType);
$form->submit($binder->bind($json, $form));
JSON Parsing Errors
if (json_validate($jsonString)) {
$form->submit($binder->bind($jsonString, $form));
}
json_last_error() for debugging.Nested Data Mismatches
{"user":{"name":"John"}}), ensure your form type matches:
# UserFormType.yaml
user:
type: entity
class: App\Entity\User
Case Sensitivity
// JSON: {"FirstName":"John"} → Form field must be "FirstName", not "firstName".
Log Bound Data
$boundData = $binder->bind($jsonString, $form);
\Log::debug('Bound data:', [$boundData]);
Check Form Errors
if (!$form->isValid()) {
\Log::error('Form errors:', $form->getErrors(true));
}
Custom Binders
Extend JsonFormBinder for custom logic:
class CustomBinder extends JsonFormBinder
{
protected function transformData($data, FormInterface $form)
{
// Custom transformation (e.g., snake_case to camelCase)
return parent::transformData($data, $form);
}
}
Symfony Form Integration Use with Laravel's Symfony bridge:
use Symfony\Component\Form\FormFactoryInterface;
$formFactory = app(FormFactoryInterface::class);
$form = $formFactory->create(YourFormType::class);
API Resource Serialization Combine with Fractal/Zizaco/ApiResource for consistent JSON responses:
$transformer = new YourTransformer($form->getData());
return response()->json(Fractal::create($transformer)->toArray());
No Laravel-Specific Config The package is agnostic to Laravel’s config. Use dependency injection for the binder:
$this->app->bind(JsonFormBinder::class, function ($app) {
return new JsonFormBinder();
});
Form Type Prioritization If binding fails, verify:
How can I help you explore Laravel packages today?