n8n-nodes-jsonata-mapper
v1.3.10
Published
An n8n community node for JSON-to-JSON mapping, JSONata transformations, JSON Schema validation, and AI-assisted mapping generation.
Downloads
635
Maintainers
Readme
n8n-nodes-jsonata-mapper
A community node for n8n that maps, transforms, and validates JSON documents using JSONata expressions and JSON Schema.
This node is designed for integration workflows where data from one JSON structure needs to be transformed into another structure in a controlled, repeatable, and testable way.
Features
- Map source JSON fields to target JSON paths
- Use JSONata expressions for flexible transformations
- Support nested target paths using dot notation
- Convert, clean, and reshape JSON data
- Validate source JSON using JSON Schema
- Validate mapped output using target JSON Schema
- Support default values for missing fields
- Support required field checks
- Optional preset transforms
- Optional JavaScript field transforms for trusted self-hosted environments
- AI-assisted mapping generation using generic LLM providers
- Debug output for troubleshooting mappings
Supported LLM Providers
The AI mapping feature supports multiple LLM providers:
- OpenAI-compatible Chat Completions APIs
- OpenRouter
- Anthropic Claude Messages API
- Google Gemini Generate Content API
- Ollama local models
- Custom HTTP JSON endpoints
The AI feature can generate JSONata mapping configurations from source JSON, target JSON, and optional JSON Schemas.
Installation
Install this package from n8n Community Nodes:
n8n-nodes-jsonata-mapperIn n8n:
Settings → Community Nodes → InstallEnter:
n8n-nodes-jsonata-mapperNode Name
After installation, search for:
JSONata MapperBasic Usage
Create a workflow like this:
Manual Trigger
↓
JSONata MapperSelect:
Operation: Apply Mapping
Source Document Mode: Paste Source JSON DocumentExample source JSON:
{
"customer": {
"firstName": "John",
"lastName": "Smith",
"email": " [email protected] "
},
"order": {
"total": "245.5"
}
}Example mapping config:
{
"version": "1.1",
"engine": "jsonata",
"mappings": [
{
"target": "person.givenName",
"expression": "customer.firstName",
"required": true
},
{
"target": "person.familyName",
"expression": "customer.lastName",
"required": true
},
{
"target": "contact.email",
"expression": "$lowercase($trim(customer.email))",
"required": true
},
{
"target": "purchase.amount",
"expression": "$number(order.total)",
"required": false
}
]
}Output:
{
"person": {
"givenName": "John",
"familyName": "Smith"
},
"contact": {
"email": "[email protected]"
},
"purchase": {
"amount": 245.5
}
}Mapping Config Format
{
"version": "1.1",
"engine": "jsonata",
"mappings": [
{
"id": "map_001",
"sourceLabel": "Customer First Name",
"target": "person.givenName",
"expression": "customer.firstName",
"required": true,
"defaultValue": "Unknown"
}
]
}Mapping Fields
| Field | Required | Description |
|---|---:|---|
| target | Yes | Target JSON path using dot notation |
| expression | Yes | JSONata expression evaluated against source JSON |
| required | No | Fails execution if the expression returns empty |
| defaultValue | No | Value used when expression returns empty |
| transform | No | Optional preset or JavaScript transform applied after JSONata |
| sourceLabel | No | Human-readable source field label |
| confidence | No | Useful for AI-generated mappings |
| reason | No | Explanation for AI-generated mappings |
JSONata Examples
Direct field mapping
{
"target": "person.givenName",
"expression": "customer.firstName"
}Trim and lowercase email
{
"target": "contact.email",
"expression": "$lowercase($trim(customer.email))"
}Convert string to number
{
"target": "purchase.amount",
"expression": "$number(order.total)"
}Array projection
{
"target": "items",
"expression": "order.lines.{\"sku\": sku, \"quantity\": qty, \"lineAmount\": $number(price) * $number(qty)}"
}Preset Transforms
Preset transforms can be used after the JSONata expression is evaluated.
{
"target": "contact.email",
"expression": "customer.email",
"transform": {
"type": "preset",
"name": "lowercaseTrim"
}
}Supported preset transforms:
lowercaseTrim
uppercaseTrim
trim
toNumber
toString
toBooleanJavaScript Field Transforms
JavaScript field transforms are an optional advanced feature. For most mappings, use JSONata or preset transforms first.
A JavaScript transform runs after the JSONata expression has produced a value.
The execution order is:
Source JSON
↓
JSONata expression
↓
Default value check
↓
Required field check
↓
Optional preset or JavaScript transform
↓
Write to target pathWhen to use JavaScript transforms
Use JavaScript transforms only when JSONata or preset transforms are not enough, for example:
- Complex business calculations
- Special date formatting
- Conditional formatting rules
- Custom lookup logic
- Data cleanup that is easier to express in JavaScript
How it works
A JavaScript transform receives two variables:
| Variable | Meaning |
|---|---|
| value | The value returned by the JSONata expression |
| source | The full source JSON document |
The code must return the final value.
Example:
{
"target": "purchase.amountWithTax",
"expression": "order.total",
"transform": {
"type": "javascript",
"code": "return Number(value) * 1.1;"
}
}If the source JSON is:
{
"order": {
"total": "245.5"
}
}The output is:
{
"purchase": {
"amountWithTax": 270.05
}
}Using full source JSON inside JavaScript
{
"target": "customer.displayName",
"expression": "customer.firstName",
"transform": {
"type": "javascript",
"code": "return value + ' ' + source.customer.lastName;"
}
}JavaScript transforms are disabled by default
To use JavaScript transforms, enable this node option:
Enable JavaScript Field TransformsIf this option is off and a mapping contains "type": "javascript", the node will fail with an error. This is intentional.
Security note
JavaScript transforms execute user-provided JavaScript. Keep them disabled unless you are running in a trusted self-hosted environment and you trust the mapping configuration.
Safer alternatives are:
- JSONata expressions
- Preset transforms
- Separate n8n Code node with controlled code
JSON Schema Validation
You can validate the source JSON, mapped output, or both.
When Use Source JSON Schema or Use Target JSON Schema is enabled, the node now checks that the corresponding schema is actually provided and meaningful. Empty schemas such as {} or non-restrictive object schemas such as { "type": "object", "properties": {} } are rejected with a clear error.
This prevents a common mistake where schema validation appears to be enabled, but the schema does not actually validate anything.
A meaningful schema should include validation rules such as:
- non-empty
properties - non-empty
required additionalProperties: falseenumorconstoneOf,anyOf, orallOf- type-specific rules such as
format,pattern,minLength,minimum, ormaximum
Source JSON Schema Example
{
"type": "object",
"required": ["customer", "order"],
"properties": {
"customer": {
"type": "object",
"required": ["firstName", "lastName", "email"],
"properties": {
"firstName": { "type": "string" },
"lastName": { "type": "string" },
"email": { "type": "string", "format": "email" }
}
},
"order": {
"type": "object",
"required": ["total"],
"properties": {
"total": { "type": "string" }
}
}
}
}Enable:
Use Source JSON Schema: true
Validate Source With Schema: trueTarget JSON Schema Example
{
"type": "object",
"required": ["person", "contact", "purchase"],
"properties": {
"person": {
"type": "object",
"required": ["givenName", "familyName"],
"properties": {
"givenName": { "type": "string" },
"familyName": { "type": "string" }
}
},
"contact": {
"type": "object",
"required": ["email"],
"properties": {
"email": {
"type": "string",
"format": "email"
}
}
},
"purchase": {
"type": "object",
"required": ["amount"],
"properties": {
"amount": { "type": "number" }
}
}
}
}Enable:
Use Target JSON Schema: true
Validate Output With Target Schema: trueAI-Assisted Mapping
The node can generate mapping suggestions using an LLM.
Select:
Operation: Generate AI MappingProvide:
- Source JSON document
- Target sample JSON
- Optional source JSON Schema
- Optional target JSON Schema
- LLM provider credentials
The AI returns a mapping config that can be reviewed and used with the Apply Mapping operation.
LLM Provider Examples
OpenAI-compatible
Provider: OpenAI-Compatible Chat Completions
Base URL: https://api.openai.com/v1
Model: gpt-4.1-miniOpenRouter
Provider: OpenAI-Compatible Chat Completions
Base URL: https://openrouter.ai/api/v1
Model: openai/gpt-4o-miniAnthropic Claude
Provider: Anthropic Claude Messages API
Base URL: https://api.anthropic.com/v1
Model: claude-3-5-sonnet-latestGoogle Gemini
Provider: Google Gemini Generate Content API
Base URL: https://generativelanguage.googleapis.com/v1beta
Model: gemini-1.5-flashOllama
Provider: Ollama Local Chat API
Base URL: http://host.docker.internal:11434
Model: llama3.1When using Docker, host.docker.internal is usually required to reach Ollama running on the host machine.
Gemini Direct API Notes
For Google Gemini direct API, use:
LLM Provider: Google Gemini Generate Content API
Base URL: https://generativelanguage.googleapis.com/v1beta
Model: gemini-2.5-flashDo not put /models/...:generateContent in the Base URL. The node builds that endpoint automatically. If you paste a full Gemini endpoint or models/<model> into the model field, the node normalizes it before calling Gemini.
Recommended Gemini models for new projects include gemini-2.5-flash and gemini-2.5-flash-lite. Older 1.5 model aliases may return 404 depending on API access and lifecycle.
Operations
| Operation | Description | |---|---| | Apply Mapping | Applies the JSONata mapping and returns transformed JSON | | Validate Mapping | Validates mapping config, JSONata expressions, schemas, and optionally output | | Generate AI Mapping | Calls a configured LLM provider to generate mappings | | Generate AI Prompt Only | Returns the prompt without calling an LLM |
Debugging
Turn on:
Return Debug InfoThis returns:
{
"mapped": {},
"debug": [],
"sourceJsonUsedByMapper": {}
}Use this to troubleshoot:
- Which expression ran
- What value was produced
- Whether a transform was applied
- Which source JSON was used
Turn it off for clean production output.
Current External Libraries
This package uses current stable library versions in package.json:
| Library | Purpose |
|---|---|
| jsonata | JSON expression and transformation engine |
| ajv | JSON Schema validation |
| ajv-formats | Email, date, URI and other JSON Schema format validation |
| Built-in path helpers | Reading source paths and writing nested target paths without deprecated lodash helpers |
The package currently targets JSONata 2.x and Ajv 8.x.
Local Development
Install dependencies:
npm installBuild:
npm run buildRun tests:
npm run test:allRelease
This package includes an n8n-style release script.
Before release, build and test locally:
npm install
npm run test:allLog in to npm:
npm login
npm whoamiRun the release command:
npm run releaseThe release script uses n8n-node release. For a direct npm publish flow, you can also run:
npm publishPackage author is set to @vvrr174.
Testing
The package includes tests for:
- Direct nested mappings
- JSONata functions
- Default values
- Required fields
- Preset transforms
- JavaScript transform enable/disable behavior
- Array projections
- Bracket path array targets
- Invalid config handling
- Invalid JSONata expressions
- Source JSON Schema validation
- Target JSON Schema validation
- Empty/non-restrictive schema toggle rejection
- Invalid schema definition rejection
- Email format validation
- AI mapping prompt generation
- Package metadata validation
Run:
npm run test:allDocker Testing With n8n
Create a temporary n8n container:
docker run -d \
--name n8n-test \
-p 5680:5678 \
-v n8n_test_data:/home/node/.n8n \
n8nio/n8n:latestCopy the package into the container:
docker cp ./n8n-nodes-jsonata-mapper n8n-test:/home/node/.n8n/nodes/n8n-nodes-jsonata-mapperInstall inside the container:
docker exec -it n8n-test sh
cd /home/node/.n8n/nodes
npm install ./n8n-nodes-jsonata-mapper
exitRestart:
docker restart n8n-testOpen:
http://localhost:5680Search for:
JSONata MapperSecurity Notes
JavaScript transforms execute user-provided JavaScript. Keep them disabled unless you are running in a trusted self-hosted environment.
For most mappings, JSONata expressions and preset transforms are safer and should be preferred.
License
MIT
npm Build and Release Notes
This package can be built and published with standard npm commands.
npm install
npm run build
npm run test:all
npm pack --dry-run
npm publishThe release script uses npm directly:
npm run releaseThis package does not require @n8n/node-cli for normal npm publishing.
Troubleshooting
Error: Bad escaped character in JSON
If n8n shows this error while installing or loading the community node:
Error loading package "n8n-nodes-jsonata-mapper":
Bad escaped character in JSON at position 11 (line 2 column 10)This usually means one JSON parameter default in the published node package is being parsed by n8n and contains bad escaping.
This package avoids that issue by generating all JSON parameter defaults using JSON.stringify(...) constants instead of manually escaped JSON strings.
The package also includes a test to validate all node JSON defaults before publishing:
pnpm run test:json-defaultsBefore publishing, run:
pnpm run test:all
npm pack --dry-runGemini returns 404 during AI mapping
Use these settings for the direct Gemini API:
LLM Provider: Google Gemini Generate Content API
Base URL: https://generativelanguage.googleapis.com/v1beta
AI Model: gemini-2.5-flashDo not include /models/... in the Base URL. The node builds the full Gemini endpoint internally.
Dependency Notes
This package does not use lodash.get or lodash.set. Nested source path reading and target path writing are handled by small internal helper functions, avoiding deprecated lodash helper packages.
Compatibility
This package is intended for self-hosted n8n community-node installations.
It uses external runtime dependencies:
- jsonata
- ajv
- ajv-formats
Because of these dependencies, it is not currently n8n Cloud verified. Self-hosted n8n installations can install and use the package normally.
