Server

Enriching, Extending and Overriding Existing Marshallers

Updated: March 18, 2024

The Nuxeo Platform provides a flexible JSON marshalling. But sometimes, you'd like to add information from your Information System to the existing JSON or even override it to match your end-user needs.

There may be different needs:

  • Add information related to the marshalled object: Try to use built-in parameters, or else create an enricher.

  • Add existing informations to the JSON: Try to use built-in parameters, or else extend the existing marshaller.

  • Change the existing JSON: Override the existing marshaller.

Enriching an Existing Marshaller

The enrichment mechanism is only enabled for the existing marshallers which extend ExtensibleEntityJsonWriter . That means, almost all of them support enrichment.

An enrichable JSON object provides a contextParameters field which contains all contributions. An enricher is activated if its name is specified in the parameters (for example: enrichers.document=breadcrumb,children). The enricher must write 0, 1 or many key-value in the current JsonGenerator and must let the JsonGenerator in the same state it got it.

Enrichment's destination

{
    ... // the existing generated object
    contextParameters: {  // only present if at least one enricher is activated
        "theFirstEnricherKey": "theFirstEnricherValue",
        "theSecondEnricherKey": { ... },
        "theThirdEnricherKey-Entry1": { ... },
        "theThirdEnricherKey-Entry2": { ... }
    }
}

Let's take the breadcrumb enricher as an example. It contributes to the generated JSON for a document and adds all of the parent documents.

ChildrenJsonEnricher

@Setup(mode = Instantiations.SINGLETON, priority = Priorities.REFERENCE)
public class BreadcrumbJsonEnricher extends AbstractJsonEnricher<DocumentModel> { // <= enrich DocumentModel Java type
    public BreadcrumbJsonEnricher() {
        super("breadcrumb"); // <= is activated if "children" is in "enrichers.document" parameter's values
    }
    public void write(JsonGenerator jg, DocumentModel document) throws IOException {
        List<DocumentModel> parentDocuments = null;
        try (SessionWrapper wrapper = ctx.getSession(document)) {
            parentDocuments = wrapper.getSession().getParentDocuments(document.getRef());
        }
        jg.writeFieldName("breadcrumb"); // <= write "breadcrumb" as key
        writeEntity(documentList, jg); // delegates the parent documents marshalling to Nuxeo
    }
}

Of course, like any JSON marshaller, you have to register it.

marshallers-contrib.xml

<?xml version="1.0"?>
<component name="org.nuxeo.example.marshallers">
    <extension target="org.nuxeo.ecm.core.io.MarshallerRegistry" point="marshallers">
        <register class="org.nuxeo.example.BreadcrumbJsonEnricher" enable="true" />
    </extension>
</component>

That's all, you can now use it!

Curl calls

$ curl -X GET 'http://localhost:8080/nuxeo/site/api/v1/path/to/my/document?enrichers.document=breadcrumb'

All existing endpoints which return a DocumentModel will handle the registered enricher.

Extending an Existing JSON Marshaller

If you want to add information at the root level of the existing JSON (not in a contextParameters sub object), you can extend an existing marshaller.

The extending mechanism is only enabled for the existing marshallers which extend ExtensibleEntityJsonWriter . That means, almost all of them support it.

That could be dangerous if you use some JSON attributes which name already exists is the inherited JSON. Double check it!

Let's take an example with the DocumentModel. The current marshaller class for DocumentModel is DocumentModelJsonWriter.

Extended marshaller

@Setup(mode = Instantiations.SINGLETON, priority = Priorities.OVERRIDE_REFERENCE) // <= an higher priority is used
public class MyCustomDocumentModelJsonWriter extends DocumentModelJsonWriter { // <= override the class
    protected void extend(DocumentModel document, JsonGenerator jg) throws IOException { // <= just implement the inherited extend method
        super.extend(document, jg); // optionnal
        jg.writeStringField("additional", "information"); // feel free to write anything
    }
}

Don't forget to register the marshaller. The resulting object will contain the whole existing JSON with your additional data.

All existing endpoints which return a DocumentModel will return the extended JSON.

Overriding an Existing JSON Marshaller

In this case, you want to completely rewrite an existing JSON.

Be careful with this approach, the marshallers provided by Nuxeo are used in many provided tools and screens. If you change it, you may break some existing components.

Custom marshaller

@Setup(mode = Instantiations.SINGLETON, priority = Priorities.OVERRIDE_REFERENCE) // <= an higher priority is used
public class MyCustomDocumentModelJsonWriter extends AbstractJsonWriter<DocumentModel> {
    public void write(DocumentModel document, JsonGenerator jg) throws IOException {
        // generate what you want
    }
}