Problem/Motivation
Looking at #2626924: [PP-1] Expose TextItems'"processed" property when normalizing
To accomplish this
- We are adding 2 computed field properties to
TextItemBase
. - Then we also have to create 2
TextItemNormalizer
s, one for the Serialization module (default normalization) and one for the HAL module (HAL normalization). - Then of course we need the tests for the normalizers.
Then in #2825812: ImageItem normalizer should expose all public image style URLs which has similar problem of exposing extra read-only information to normalization
We accomplish this by:
- Creating two ImageItemNormalizers , one for Serialization and one for Hal.
- Then of course we need the tests for the normalizers.
- But in this case we don't add the computed field properties ImageItem
You could see how this could get complicated very quickly as we find new information related to field items that we want to include in normalization.
This doesn't take into account contrib modules like JSON API that also do normalization. It would need to duplicate these normalizers.
If we want to do it in the manner of processed text above we would need at least 1 computed field property and then 2 normalizers each time(default normalization provided by the serialization
module and HAL normalization for the hal
module, with tests).
We could do it like the Image Style URLs which does still require 2 new normalizers but not the computed fields. The problem with this is then the adding of the image_styles
in the normalization is completely unknown to the Typed Data API.
This makes automatically documenting what is in our REST responses(or JSON API) very difficult.
Indeed combining the Schemata module and OpenAPI you can start get pretty decent documentation for our REST resources. But this relies on converting Typed Data to a schema (e.g. JSON Schema).
But if we continue to add extra information in normalizers that aren't reflected in Typed Data at all, then Schemata or any other way we try to automatically document the schema for our resources will always be incomplete. :(
We can't rely on computed fields alone because \Drupal\jsonapi\Normalizer\FieldItemNormalizer
uses \Drupal\serialization\Normalizer\ComplexDataNormalizer::normalize()
which has
/** @var \Drupal\Core\TypedData\TypedDataInterface $field */
foreach ($object as $name => $field) {
$attributes[$name] = $this->serializer->normalize($field, $format, $context);
}
Using foreach
with anything that extends \Drupal\Core\Field\FieldItemBase
will ultimately call \Drupal\Core\TypedData\Plugin\DataType\Map::getProperties()
which doesn't include computed properties.
We could override this in FieldItemNormalizer
to normalize all properties both computed and non-computed. But then we run into the problem that we are already using computed fields for things like the entity
property in EntityReferenceItem
. An we don't know what else contrib might be using for computed properties.
We could required each field type (each \Drupal\Core\Field\FieldItemInterface
implementation) to specify which computed items should NOT be normalized but doing that now would be a BC break.
Proposed resolution
So in order to included only the computed fields we want in normalization we need to allow field types to opt in only specific computed fields.
We can do this by adding a new property, $export_computed_properties
, to \Drupal\Core\Field\Annotation\FieldType
.
This property would default to an empty array so no existing computed fields would be included by default.
Then in \Drupal\serialization\Normalizer\FieldItemNormalizer
and \Drupal\serialization\Normalizer\FieldItemNormalizer
(and maybe JSON API?) we call a shared ComputedPropertiesNormalizerTrait
that will include the computed properties specified in $export_computed_properties
for the field type.
Then field types like TextItem
and ImageItem
can create computed fields and just include that ones that should be included in any kind of export in $export_computed_properties
.
This eliminates the need to make 2 new normalizers (not counting JSON API) for every case where we want to add extra information in the normalization.
It also means that since we will be using Typed Data and explicitly defining which computed properties will be in the normalization (or other exports) we easily/automatically document these in auto-generated REST (and JSON API) documentation.
Remaining tasks
Decide if this is good idea!
User interface changes
API changes
Data model changes