Skip to content

[5.x]: JSON field's normalizeValueFromRequest doesn't support posted array data #18696

@samhibberd

Description

@samhibberd

What happened?

Description

Currently, the JSON field's normalizeValueFromRequest method attempts to JSON-decode the raw posted value, which means it only accepts string input (a JSON-encoded string). This prevents submitting structured data to a JSON field using standard HTML form array syntax.

The problem

If you post data like:

<input type="hidden" name="fields[myJsonField][ids][]" value="1">
<input type="hidden" name="fields[myJsonField][ids][]" value="2">

PHP delivers this to the method as an already-decoded array:

['ids' => ['1', '2']]

But the method passes it to JsonHelper::decode(), which expects a string. This causes it to either throw an exception or produce an error array, even though the data is perfectly valid.

Relevant code

JsonField::normalizeValueFromRequest:

public function normalizeValueFromRequest(mixed $value, ?ElementInterface $element): mixed
{
    if ($value === null || $value === '') {
        return null;
    }
 
    try {
        $value = JsonHelper::decode($value);
    } catch (InvalidArgumentException $e) {
        $value = [
            '__ERROR__' => $e->getMessage(),
            '__VALUE__' => $value,
        ];
    }
 
    return new JsonData($value);
}

Expected behavior

When the posted value is already an array (or other non-string type that's valid as JSON data), the method should accept it directly rather than attempting to JSON-decode it. A possible approach:

if (is_string($value)) {
    try {
        $value = JsonHelper::decode($value);
    } catch (InvalidArgumentException $e) {
        $value = [
            '__ERROR__' => $e->getMessage(),
            '__VALUE__' => $value,
        ];
    }
}

Use case

This would allow front-end forms and integrations to post structured data into JSON fields using conventional form field naming, which is a natural pattern when building forms that collect multi-value or nested data destined for a JSON field.

We acknowledge there may be security or validation implications we haven't fully considered - but we'd love to see this supported if feasible.

Craft CMS version

5.9.19

PHP version

8.2

Operating system and version

No response

Database type and version

No response

Image driver and version

No response

Installed plugins and versions

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions