I'm trying to extend Serialization to get the JSON Field module to return a JSON object instead of stringified JSON.
Goal: When I access an entity that contains a JSON field using JSON:API, I want a JSON object for the field value (currently, the stringified JSON is returned).
I think what I need to do is to extend one of the core normalizers and use it to add a json_decode()
step.
There is some documentation on how Serializer handles entities but it is out-of-date (last updated in 2017 before JSON:API was part of core, and the current code looks nothing like what is shown.)
I tried extending FieldNormalizer in /json_field/src/Normalizer/JsonFieldNormalizer.php
.
However, I'm not confident that this is the correct approach, as there is also a FieldItemNormalizer and TypedDataNormalizer. To change how a field is output in JSON:API, which class should I extend?
<?php
namespace Drupal\json_field\Normalizer;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\json_field\Plugin\Field\FieldType\NativeJSONItem;
use Drupal\jsonapi\JsonApiResource\ResourceObject;
use Drupal\jsonapi\Normalizer\FieldNormalizer;
use Drupal\jsonapi\Normalizer\Value\CacheableNormalization;
use Drupal\jsonapi\ResourceType\ResourceType;
class JsonFieldNormalizer extends FieldNormalizer {
/**
* {@inheritdoc}
*/
protected $supportedInterfaceOrClass = NativeJSONItem::class;
/**
* {@inheritdoc}
*/
public function normalize($field, $format = NULL, array $context = []) {
$field_name = $field->getName();
\Drupal::logger('json_field')->info("Field has name $field_name");
assert($field instanceof NativeJSONItem);
/** @var \Drupal\Core\Field\FieldItemListInterface $field */ $normalized_items = $this->normalizeFieldItems($field, $format, $context);
assert($context['resource_object'] instanceof ResourceObject);
return $context['resource_object']->getResourceType()->getFieldByInternalName($field->getName())->hasOne()
? array_shift($normalized_items) ?: CacheableNormalization::permanent(NULL)
: CacheableNormalization::aggregate($normalized_items);
}
And I added the class to json_field.services.yml
:
services:
json_field.views:
class: Drupal\json_field\JSONViews
json_field.normalizer.field.json_field:
class: Drupal\json_field\Normalizer\JsonFieldNormalizer
tags:
- { name: normalizer, priority: 1 }
However, after rebuilding the cache and accessing some JSON fields via JSON:API, I don't see anything in the logs, so it seems like the class is not being picked up.