Skip to content

Serialization groups ​

Roadiz CMS uses symfony/serializer to perform JSON serialization over any objects, especially Doctrine entities.

GroupDescription
idSerialize every entity id.
attributeSerialize entities in a Attribute context.
attribute_documentsSerialize documents linked to a Attribute for each virtual field.
attribute_groupSerialize Attribute group name and translations.
attribute_nodeSerialize AttributeValue in a node context (node-specific attribute values).
breadcrumbsSerialize breadcrumb trail items within a web_response context.
childrenSerializes a node along with its children using a treeWalker.
colorSerialize every entity color fields.
custom_formSerialize entities in a CustomForm context.
custom_form_answerSerialize CustomFormAnswer entity with its submission fields.
documentSerialize entities in a Document context.
document_copyrightSerialize Document copyright validity date range (copyrightValidSince, copyrightValidUntil).
document_displaySerialize Document information required for displaying them.
document_display_sourcesSerialize Document information required for displaying alternative sources (audio, video).
document_sourceSerialize minimal Document information for an alternative source (mimeType, type, relativePath).
document_filesizeSerialize Document filesize in bytes.
document_foldersSerialize Document information required for displaying attached visible folders.
document_folders_allSerialize all Document attached folders, even not visible ones.
document_mountSerialize Document storage mount path prefix.
document_originalSerialize Document original reference (for thumbnail documents pointing back to their original).
document_raw_relative_pathSerialize rawRelativePath when document has a RAW version and make it downloadable.
document_thumbnailsSerialize Document first available thumbnail.
folderSerialize entities in a Folder context.
folder_childrenSerialize Folder children.
folder_colorSerialize Folder color field.
folder_parentSerialize Folder parent.
logSerialize Log entity core fields.
log_sourcesSerialize node/source context on Log entries.
log_userSerialize user context on Log entries.
nodeSerialize entities in a Node context.
node_attributesSerialize Nodes with their attribute values.
node_childrenSerialize Nodes with their children.
node_listingSerialize Nodes and NodesSources with their listing children options.
Adds listingSortOptions field to node-sources, with for example { "node.position": "ASC" } to be able to fetch children nodes in the same order as in the back office.
If the current serialized node-source parent is hiding its children, listingSortOptions will contain the parent's listingSortOptions instead.
node_typeSerialize entities in a NodeType context.
nodes_sourcesSerialize entities in a NodesSources context (all fields).
nodes_sources_baseSerialize entities in a NodesSources context, but with essential information.
nodes_sources_defaultSerialize NodesSources fields not contained in any group.
nodes_sources_documentsSerialize documents linked to a NodesSources for each virtual field.
nodes_sources_publishedSerialize NodesSources isPublished field when you fetch all NodesSources, even the unpublished ones.
nodes_sources_xxxxCustom serialization groups are created according to your node-type fields groups.
For example, if you set a field to a link group, nodes_sources_link serialization group will be automatically generated for this field.
Be careful, Roadiz will use groups canonical names to generate serialization groups, it can mix _ and -.
positionSerialize every entity position fields.
realmSerialize Realm access-control entity fields.
settingSerialize entities in a Setting context.
setting_groupSerialize entities in a SettingGroup context.
tagSerialize Tag.
tag_baseSerialize Tags with minimum information.
tag_childrenSerialize Tags with their children, do not use with tag_parent group.
tag_colorSerialize Tags with their color field.
tag_documentsSerialize Tags with their documents.
tag_parentSerialize Tags with their parent.
timestampsSerialize every date-timed entity createdAt and updatedAt fields.
translated_tagSerialize Tag with its translations collection.
translationSerialize entities in a Translation context.
translation_baseSerialize Translation information required for displaying them.
url_aliasSerialize UrlAlias entity fields.
urlsSerialize the url fields of every entity.
userSerialize entities in a User context.
user_chrootSerialize User chroot node restriction.
user_groupSerialize User entity with its groups.
user_identifierSerialize User entity with its identifier (may be a personal information).
user_personalSerialize User entity with its personal information.
user_publicSerialize public-facing User fields from AbstractHuman.
user_roleSerialize User entity with its roles.
user_securitySerialize User security and authentication fields.
walkerSerializes a treeWalker children.
walker_metadataSerializes a treeWalker metadata.
web_responseSerialize the top-level WebResponse API envelope fields.

Enriching normalized items ​

To add or change fields in the API Platform output of an entity, implement RZ\Roadiz\CoreBundle\Serializer\Enricher\NormalizationEnricherInterface. Enrichers are autoconfigured, and a single EnrichingItemNormalizer (decorating api_platform.jsonld.normalizer.item and api_platform.serializer.normalizer.item) runs them after API Platform has normalized the object.

php
namespace App\Serializer\Enricher;

use App\GeneratedEntity\NSMenuLink;
use RZ\Roadiz\CoreBundle\Serializer\Enricher\NormalizationEnricherInterface;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

final readonly class MenuLinkPathEnricher implements NormalizationEnricherInterface
{
    public function __construct(private UrlGeneratorInterface $urlGenerator)
    {
    }

    public function supports(object $data, ?string $format, array $context): bool
    {
        return $data instanceof NSMenuLink;
    }

    /**
     * @param NSMenuLink $data
     */
    public function enrich(array $normalized, object $data, ?string $format, array $context): array
    {
        $target = $data->getLinkInternalReferenceSources()[0] ?? null;
        $normalized['url'] = null !== $target
            ? $this->urlGenerator->generate(RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, [
                RouteObjectInterface::ROUTE_OBJECT => $target,
            ])
            : $data->getLinkExternalUrl();

        return $normalized;
    }
}
  • supports() is called for every normalized object: keep it cheap, instanceof first.
  • enrich() only runs when API Platform returned an array (not an IRI string).
  • Each enricher run is measured in the Symfony profiler under the serializer Stopwatch category, there is no need to add your own.

Ordering ​

Enrichers run in descending tag priority, set with #[AsTaggedItem(priority: …)] (default 0). Core enrichers use the following priorities, so pick yours accordingly:

PriorityEnricher
21FolderEnricher
20DocumentEnricher
19DocumentSourcesEnricher
18TagTranslationEnricher
15AttributeValueEnricher, CustomFormEnricher
5NodesSourcesPathEnricher (adds url unless already set)
-10NodesSourcesTypeEnricher (JSON-LD @type only)

Normalizing nested objects ​

When an enricher adds related objects (documents, folders…), normalize them through the Serializer: implement Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface (with NormalizerAwareTrait) and call $this->normalizer->normalize($related, $format, $context). The EnrichingItemNormalizer injects the Serializer for you. Never call an inner normalizer directly: other enrichers and project decorators would not apply to the nested objects. Restrict $context['groups'] for nested objects to avoid normalization loops.

Migrating from AbstractPathNormalizer ​

AbstractPathNormalizer decorators still work, but are deprecated: each one adds a layer to every supportsNormalization() call the Serializer makes, for every normalized object. To migrate one:

  1. Implement NormalizationEnricherInterface instead of extending AbstractPathNormalizer.
  2. Move the instanceof and context checks into supports().
  3. Move the code that runs after $this->decorated->normalize() into enrich(), and return the array.
  4. Replace $this->decorated->normalize($nested, …) with $this->normalizer->normalize($nested, …) (see above).
  5. Remove both decorates: service definitions from config/services.yaml. Convert their decoration_priority into an #[AsTaggedItem] priority if order matters.