API Platform version(s) affected: 2.5.6
Description
Hi, I have a concern that Json:Api response formatting isn’t working properly if an output class is being used for API resource (“relationships”, “links”, “meta”, "included" fields are missing)
A check if the output class is being used is performed here: https://github.com/api-platform/core/blob/9ccf57835b3a4f0c54cbde1ef43af193bf689b34/src/JsonApi/Serializer/ItemNormalizer.php#L71
and if it is, an AbstractItemNormalizer->normalize() method is called.
Data is then transformed and execution proceeds as such:
AbstractItemNormalizer->normalize() =>
Symfony/Serializer->normalize() =>
JsonApi/ObjectNormalizer->normalize()
In the JsonApi/ObjectNormalizer->normalize() Json:Api specific fields are added (“id”, “type”, “attributes”)
My concern is that the code below the if-statement linked above never gets executed.
This results in the resource metadata (links, meta, relationships) not being applied to the response object.
Can someone please help understand is this actually the case or I’m misinterpreting something?
Thanks 😃
How to reproduce
If these steps are not enough, I can provide code snippets.
Hi!
I've just run into this also. As soon as you use output="", the entire normalization process changes. The issue starts at the top-level AbstractItemNormalizer:
public function normalize($object, $format = null, array $context = [])
{
if (!($isTransformed = isset($context[self::IS_TRANSFORMED_TO_SAME_CLASS])) && $outputClass = $this->getOutputClass($this->getObjectClass($object), $context)) {
// ...
return $this->serializer->normalize($transformed, $format, $context);
}
// the rest of the normal logic that's used for normalization, including
// calling parent::normalize() (AbstractObjectNormalizer) which has a TON of logic
// related to circular references, max depth and using ApiPlatform's PropertyMetadataFactory
// to assist in fetching the values of attributes and normalizing collections/embedded ApiResources
}
Effectively, by choosing an output=Something::class, you completely change the logic that's used
for normalization. This might be intended (?) - it's just not clear :).
On a more practical note, if you use JSON-LD, you get the @id but you lost the @type field on the output JSON.
It's intended indeed as our normalizer only handles classes marked as ApiResource and it's very difficult to use the same normalization with classes that aren't (DTOs / non-resource classes). Also, these data transfer object have a different representation as they represent a resource. With Json-ld for example the @id should be the one of the underlying Resource, but as it's @type is not the one of the resource, the context gets embedded. At least this is what I remember from the discussions on the subject.
History of the work on this topic: