Skip to main content

Mappings

Overview​

A Mapping defines how to transform data from one shape to another. Mappings sit between sources and targets in a synchronization flow, and are also used by endpoints to reshape request and response bodies. The mapping engine supports direct field assignments, Twig template expressions, type casts, dot-notation paths, and JSON Logic conditions.

Mapping Object Structure​

A mapping consists of a mapping object (field assignments) and an optional cast object (type conversions):

{
"name": "ZGW Zaak to OpenRegister",
"slug": "zgw-zaak-to-openregister",
"mapping": {
"identificatie": "{{ input.zaakIdentificatie }}",
"omschrijving": "{{ input.omschrijving }}",
"startdatum": "{{ input.startdatum | date('Y-m-d') }}",
"status.code": "input.status.statustype.code",
"zaaktype": "{{ input.zaaktype | split('/') | last }}"
},
"cast": {
"bouwkosten": "integer",
"aantalBijlagen": "integer",
"metadata": "jsonToArray"
}
}

Mapping Strategies​

Direct Field Reference​

Reference source fields by dot-notation path. No Twig delimiters needed:

{
"naam": "input.naam",
"adres.straat": "input.verblijfsadres.straatnaam"
}

Twig Template Expression​

Use Twig syntax for transformations, string manipulation, conditionals, and loops:

{
"volledigeNaam": "{{ input.voornamen }} {{ input.geslachtsnaam }}",
"geboortejaar": "{{ input.geboortedatum | date('Y') }}",
"actief": "{% if input.status == 'actief' %}true{% else %}false{% endif %}"
}

Static Value​

Provide a literal value (not a path or Twig expression):

{
"bron": "TenderNed",
"versie": "1.0"
}

Nested Object Mapping​

Use dot-notation keys to build nested output structures:

{
"adres.straatnaam": "input.straat",
"adres.huisnummer": "input.nummer",
"adres.postcode": "input.postcode"
}

This produces { "adres": { "straatnaam": "...", "huisnummer": "...", "postcode": "..." } }.

Conditional Mapping​

Apply a transformation only when a JSON Logic condition is true. Use _conditions at the top level of the mapping to skip or override fields:

{
"mapping": {
"type": "{{ input.type }}"
},
"_conditions": [
{
"condition": { "!=": [{ "var": "input.type" }, null] },
"mapping": {
"type": "{{ input.type | upper }}"
}
}
]
}

Type Casts​

The cast section applies type conversions after field assignment:

CastDescription
stringConvert to string
integer / intConvert to integer
floatConvert to float
boolean / boolConvert to boolean
arrayConvert to array (wraps scalars)
jsonToArrayParse a JSON string into an object/array
dateParse and normalize date strings
urlEncode as a valid URL
unsetRemove the field from output

List Processing​

Apply a mapping to each item in an array by enabling list mode. The engine iterates over the input array and maps each item independently. Configure passlist to preserve the array structure in the output.

Twig Extensions​

The mapping engine provides custom Twig functions and filters beyond standard Twig:

ExtensionDescription
oauthToken(source)Fetch an OAuth token for a Source
jwToken(source)Generate a JWT for a Source
callService(source, endpoint, method, body)Make an HTTP call within a mapping
mappingService(mappingSlug, input)Apply another mapping recursively
Standard Twig filtersdate, split, last, upper, lower, replace, json_encode, etc.

OpenRegister Delegation​

The MappingService in Integriq delegates execution to OpenRegister's MappingService when OpenRegister is installed. This provides a shared, maintained mapping engine across the Conduction app suite. Integriq falls back to its own implementation when OpenRegister is not available.

Implementation​

  • lib/Service/MappingService.php — Twig-based mapping engine, delegation to OpenRegister
  • lib/Controller/MappingsController.php — REST CRUD API
  • lib/Db/Mapping.php — Entity
  • lib/Db/MappingMapper.php — Database mapper
  • lib/Twig/MappingExtension.php — Custom Twig functions
  • lib/Twig/MappingRuntimeLoader.php — Runtime loader for lazy-loaded Twig services