---
id: flow--data-mapper
title: "Data mapper"
summary: "Copies property values from the input record into a new record of another type, field by field, as defined in the mapping editor. Use it to turn one structure into another, for example a database row into an API request or a JSON document into a flow type."
audience: user
keywords: "input, output, mappings"
---
# Data mapper

Copies property values from the input record into a new record of another type, field by field, as defined in the mapping editor. Use it to turn one structure into another, for example a database row into an API request or a JSON document into a flow type.

## Pins

| Pin | Kind | Types | Description |
|---|---|---|---|
| Input | input | any | Source records. The type on the incoming connection is the source type of a mapping. |
| Output | output | the types of the outgoing connections | One new record per type mapping defined for the input type. Set the type on each outgoing connection; it is the target type. |

## Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `Mappings` | string (JSON, mapping editor) | | The type and field mappings, see below. |

### Mappings format

The mapping editor stores a JSON object with one entry per (source type, target type) pair:

```json
{
  "typeMappings": [
    {
      "inputName": "Customer",
      "outputName": "CrmContact",
      "sourceTypeName": "MyFlow.Customer",
      "targetTypeName": "MyFlow.CrmContact",
      "fieldMappings": [
        { "sourceFieldPath": "Name",            "targetFieldPath": "FullName" },
        { "sourceFieldPath": "Id",              "targetFieldPath": "ExternalId" },
        { "sourceFieldPath": "Address.City",    "targetFieldPath": "City" }
      ]
    }
  ]
}
```

- `sourceTypeName` / `targetTypeName`: full type names (namespace + name) as on the connections. Only these two and `fieldMappings` are used at runtime; `inputName` / `outputName` are the short names shown in the editor.
- `sourceFieldPath` / `targetFieldPath`: property names, nested properties separated by `.` (`Address.City`), case-sensitive, starting at the root of the type.
- When you open the editor it creates an empty type mapping for every pair of incoming and outgoing connection types. Drag a source field onto a target field to add a field mapping; "auto map" pairs fields with the most similar names. Mapping a nested field also adds the mappings of its parent properties (`Address` → `Addr` for `Address.City` → `Addr.Town`).

## Behaviour

- On start every type mapping is compiled. An unknown type or property, or a pair of property types that cannot be converted, makes the flow fail to start.
- For each input record the plugin looks up the type mappings whose `sourceTypeName` matches the record's type. If there is none, the record fails with "Unable to find appropriate mapper for input type". For every matching type mapping a new, empty target record is created, the mapped fields are copied, and the record is sent to `Output`. Unmapped target fields keep their default values. Metadata is passed through unchanged.
- The output is delivered to the outgoing connections whose type equals the target type.
- Type conversion: equal types are copied (objects and lists by reference). Different simple types are converted (to string, numbers, `bool`, `DateTime`, `DateTimeOffset`, `TimeSpan`, `Guid`, `decimal`, ...). Properties of type `object` are converted with the standard .NET type converter.
- An orange "no mapping" indicator is shown until every type mapping has at least one field mapping (checked when the mapping is saved).

## Notes

- Lists with different item types (`List<A>` to `List<B>`) and different complex types cannot be mapped; the flow fails to start. Because the editor adds parent mappings for nested fields, mapping `Address.City` → `Addr.Town` only works when `Address` and `Addr` have the same type. To map lists of different types use ForEach → Data mapper → Build array, or a script.
- Nested paths: when an object on a source path (or a parent object on a target path) is `null`, the remaining field mappings of that type mapping are skipped for this record, not only the one field. A dotted source path whose final value is a `null` string has the same effect. Target records are created empty, so nested target objects are normally `null`; prefer mapping to top-level target fields.
- If two outgoing connections have the same target type and the editor created two identical type mappings, each connection receives the record twice.
- Saving an empty mapping reports "The mapping definition is not set".

## Example

Http listener (`Customer`) → **Data mapper** → (`CrmContact`) Http client
