Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Nael.Saeed's avatar

Form Request Validation for JSON Parameter

Hi there,

I have an AJAX request sent to my API. This request has a parameter that should contain a JSON formatted data. I want to validate that it is actually JSON. Laravel form request has a 'json' validation rule, but the problem I am facing is that the parameter that I want to validate for JSON gets converted into an array before validation. So how am I supposed to prevent this conversion and do the validation?

Example request data:


{
    "id": 1,
    "name": "John",
    "json_data": {
        "data1": [

        ],
        "data2": [

        ]
    }
}


validation:

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules()
{

    return [
        'id' => [
            'required'  
        ],
        'title' => [
            'required',
            'string',
        ],
        'json_data' => [
            'required',
            'json',
        ],
    ];
}
0 likes
11 replies
Nakov's avatar

Can you please show an example request data and your validation code so we can try to help?

Nael.Saeed's avatar

@nakov I have updated the question with code

@robstar How would that solve the problem of json data being converted to array before applying the validation rule?

mstrauss's avatar

Can you die and dump the $request? And maybe show the (handle) controller and form that the request is sent from? Just trying to understand where the json is being transformed into an array.

Robstar's avatar

Well to validate if the data JSON, as in your OP, the Laravel docs have you covered. See https://laravel.com/docs/5.8/validation#rule-json

If you want the verify the exact JSON structure you'll need your own rule. The rule is a simple class that can accept any arguements as required i.e.

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class ValidJsonStructure implements Rule
{
    // @todo you expected structure as an array
    protected $expectedStructure = [];
    
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value): bool
    {
        // $value is json string and can be manipulated on any way
        // would recommend you can convert the JSON string to an array
        // then return based upon if the actual array structure matches
        // $this->expectedStructure;
        // return true or false to validate 
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message(): String
    {
        return 'The :attribute must have the exact, expected, JSON structure';
    }
}

Then if your Form request:

...

'json_data' => [
            'required',
            'json',
            new ValidJsonStructure,
        ],
...

Nael.Saeed's avatar

@robstar You're still not getting my problem. I am using the JSON validation rule. but the problem is that form request is converting the request data into array instead of JSON including the json_data parameter. Thus a non JSON validation error is returned for the parameter json_data even though it is a valid JSON.

Robstar's avatar

Then don;t use the built in rule.

Use a custom rule that firstly validates if the request item is json and then validates the structure.

Nael.Saeed's avatar

@robstar I am not getting this. how would the custom validation rule do the job? If the data its validating is always converted to an array before it is handled by the custom rule? even if the original data sent with the request is in JSON format?

Nakov's avatar
Nakov
Best Answer
Level 73

So the json rule validates a JSON string for a valid JSON, so the data that you are sending should be like this instead:

{
    "id": 1,
    "name": "John",
    "json_data": "{\"data1\": [], \"data2\": []}"
}

You should be able to achieve that on your JS side using JSON.stringify(jsonData);

manishanaik's avatar

I would suggest to decode the json input and validate each key, this can be done by modifying the request before its validated, e.g your json input is {"x":100,"y":120,"width":60,"height":15} so in validation rules

'json_field' => ['required', 'json'],

In case you know the number of keys in your json you can add this in rule

'json_field_as_array' => 'array|size:4',

Validation rule for each key

'json_field_as_array.x' => ['required', 'integer'],
'json_field_as_array.y' => ['required', 'integer'],
'json_field_as_array.width' => ['required', 'integer'],
'json_field_as_array.height' => ['required', 'integer'],

You can add the messages for each key like this

public function messages(): array
    {
        return [
    'json_field_as_array.x.required'=> 'The signature field.x is missing from the signee_signature_field.',
            'json_field_as_array.y.required'=> 'The signature field.y is missing from the signee_signature_field.',
            'json_field_as_array.width.required'=> 'The signature field.width is missing from the json_field_as_array.',
            'json_field_as_array.height.required'=> 'The signature field.height is missing from the json_field_as_array.',
        ]
}

You must be wondering from where this json_field_as_array field came, the answer is here, you can merge the json_field into the request by overriding the getValidatorInstance() request method

protected function getValidatorInstance(): Validator
    {
        $json = $this->request->get('json_field');
        $this->merge(['json_field_as_array' => json_decode($json, true)]);

        return parent::getValidatorInstance();
    }
Robstar's avatar

All that code would be much neater and more reusable in a rule class as described earlier.

Please or to participate in this conversation.