Conversation
A state provider can now return an ApiPlatform\Hydra\Collection instead of a bare iterable. A dedicated jsonld normalizer registered above the JSON-LD ObjectNormalizer reads the object's own fields; totalItems, view and search are emitted only when set. Collection is no longer @internal.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A state provider can now return an
ApiPlatform\Hydra\Collectioninstead of a bare iterable, and it is normalized correctly for thejsonldformat.Why
Hydra\Collectionalready exists but is only reachable from the JsonStreamer path (ApiPlatform\Hydra\State\JsonStreamerProcessor). On the Serializer path the object was claimed byApiPlatform\JsonLd\Serializer\ObjectNormalizer(priority -995), which emitted its raw public properties instead of a Hydra collection.Widening
AbstractCollectionNormalizer::supportsNormalization()to accept the class is not an option:api-platform/hydrarequiresapi-platform/serializerand not the reverse, so importingHydra\Collectionintosrc/Serializerwould invert the split-package dependency direction.What
ApiPlatform\Hydra\Serializer\CollectionObjectNormalizer, registered at priority -984, which is strictly above the JSON-LDObjectNormalizerthat would otherwise claim the object. It is a standalone service and is not part of thePartialCollectionViewNormalizer/CollectionFiltersNormalizerdecoration chain.hydra:viewandhydra:searchare emitted only when the user sets them, andhydra:totalItemsfalls back tocount()only whenmemberis countable. No pagination or parameter introspection happens.hydra:viewandhydra:searchreuse the exact shapes thatPartialCollectionViewNormalizerandCollectionFiltersNormalizeralready produce, so the output is indistinguishable from a normal collection.Collection::$idand$contextbecome nullable, andnullmeans "generate it" while an explicit value wins. They previously held a'VIRTUAL'placeholder, which exists only to keep the non-nullablestringproperties initialized for the JsonStreamer generated writer. That is a streamer implementation detail and never a "compute me" contract, so a normalizer must not read it.Hydra\Collectionis no longer@internal, since it becomes public API.$memberdocblock goes from@var list<T>to@var iterable<T>. The native type is alreadyiterableandJsonStreamerProcessorassigns paginators to it, solist<T>was wrong.Example
JsonStreamer is unaffected
src/JsonLd/JsonStreamer/WritePropertyMetadataLoader.phpgenerates@id,@typeand@contextas virtualPropertyMetadatabound to value transformers, andIriValueTransformer::transform()ignores the incoming value and recomputes from$options['_current_object']. Nullability of those two properties is therefore inert on the write path.Verified rather than assumed: the streamed body for
GET /json_stream_resourceswithapplication/ld+jsonis identical before and after the change, with@context=/contexts/JsonStreamResource,@id=/json_stream_resourcesand@type=Collectionin both.tests/Functional/JsonStreamerTest.phponly asserts key presence there, so anullwould not have failed it; the values were compared directly.Tests
src/Hydra/Tests/Serializer/CollectionObjectNormalizerTest.php(9 cases) andtests/Functional/HydraCollectionObjectTest.php.Both are green locally, together with
tests/Functional/JsonStreamerTest.php. Broader regression scope left to CI.