Skip to content

[JsonStreamer] Allow to access to current object when writing #61006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: 7.4
Choose a base branch
from

Conversation

mtarld
Copy link
Contributor

@mtarld mtarld commented Jul 1, 2025

Q A
Branch? 7.4
Bug fix? no
New feature? yes
Deprecations? no
Issues
License MIT

A new attempt to #59281.

As discussed with @soyuka, it is really important to have access to the current object during stream writing.
Without that, it'll for example be impossible for API Platform to generate resource IRIs (https://github.com/api-platform/core/blob/main/src/Metadata/IriConverterInterface.php#L46).

This PR makes is available in value transformers' $context under the _current_object key.

@soyuka
Copy link
Contributor

soyuka commented Jul 1, 2025

Indeed this is really a nice-to-have functionality. When generating Hypermedia (or probably any JSON) while streaming, it's quite useful to have the current object being serialized to change parts of the data. To illustrate, we use it to generate the IRI of a given object during serialization:

<?php

declare(strict_types=1);

namespace ApiPlatform\JsonLd\JsonStreamer\ValueTransformer;

use ApiPlatform\Hydra\Collection;
use ApiPlatform\Metadata\CollectionOperationInterface;
use ApiPlatform\Metadata\IriConverterInterface;
use ApiPlatform\Metadata\UrlGeneratorInterface;
use Symfony\Component\JsonStreamer\ValueTransformer\ValueTransformerInterface;
use Symfony\Component\TypeInfo\Type;

final class IriValueTransformer implements ValueTransformerInterface
{
    public function __construct(
        private readonly IriConverterInterface $iriConverter,
    ) {
    }

    public function transform(mixed $value, array $options = []): mixed
    {
        if ($options['_current_object'] instanceof Collection) {
            return $this->iriConverter->getIriFromResource($options['operation']->getClass(), UrlGeneratorInterface::ABS_PATH, $options['operation']);
        }

        return $this->iriConverter->getIriFromResource(
            $options['_current_object'],
            UrlGeneratorInterface::ABS_PATH,
            $options['operation'] instanceof CollectionOperationInterface ? null : $options['operation'],
        );
    }

    public static function getStreamValueType(): Type
    {
        return Type::string();
    }
}

Without this functionality we're quite locked-out when it comes to transformations like this one: it's recursive so we're using only the node being serialized, as opposed to $value.
With @mtarld we thought of multiple approaches to this problem but many would've impacted performances more then we like for this component.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants