Ditto
Declarative JSON-to-JSON mapper: shape-shift JSON files with Ditto
Ditto
Status: Stable but dormant. The was last pushed in September 2024 and sees little activity today; the library is published on npm as .
When dealing with data integration, translating JSON from external formats into an internal representation is a constant chore: every new data source arrives with its own field names and nesting. Ditto solves this declaratively. Instead of writing a bespoke transformation script per source, you write a mapping file that describes the output shape, and Ditto produces JSON from the input data to match it.
Ditto parses the mapping file (see ) and runs three stages (_preMap, _map, _postMap), where the output of each stage is fed as input to the next:
How to use Ditto
Ditto exposes a class that can be instantiated with a mapping file and an optional plugins list. Call unify with the document you want transformed:
Alternatively, create a default instance and pass both the document and the mappings to unify itself (its signature is unify(document, mappings)):
Built-in plugins are available out of the box. Extra plugins can be registered either through the addPlugins(plugins) method or by passing them to the constructor directly via new Ditto(myCustomMappings, myCustomPlugins). Added plugins extend, and never overwrite, the default set.
Plugins: transformations in the mapping file
The heart of Ditto's expressiveness is plugins: plain JavaScript functions invoked from the mapping file with the @ symbol. A plugin is nothing more than a function that takes 0+ arguments:
Arguments in the mapping file are separated by | and can be paths into the input document, hard-coded values, or defaults:
@concatName(firstName|lastName): callconcatNamewith the values extracted from thefirstNameandlastNamepaths in the input file@concatName(firstName|>>this_is_my_last_name): the>>prefix passes a hard-coded string instead of a path lookup@concatName(firstName|lastName|*>>default): the*prefix marks a default value, used when the other lookups come up empty
If a plugin might receive a variable number of arguments, the JavaScript arguments keyword handles it cleanly:
Functions in functions
A plugin's value can be fed into another plugin as a parameter by nesting the call inside the arguments. One catch: parameters of inner function calls are separated by a comma , rather than the usual |:
Plugins activation
Plugins are activated in the /ditto/plugins/plugins.js file by adding the plugin name (matching the .js filename of the definition) to the plugins array; each one is required and exported for the main mapping function:
The full list of built-in plugins lives in the , and the complete mapping-rule syntax is documented in the .