The ValueMapper plugin copies values from a source JSON to a target JSON, with optional transformations. You define rules (commands) with a source path, a target path, and optionally transformations. The first transformation that applies is executed.
- Copy a value from
sourcePointertotargetPointer. - Automatically create missing paths in the target.
- Apply a transformation to the value (e.g., copy with different value or type conversion).
- Provide a fallback
defaultValueon COPY commands so the target can still be populated even when no transformation matches or transformations are omitted. - Conditionally skip a command or transformation with a SpEL
skipCondition.
ValueMapper: executes mapping rules onsource: JsonNodeandtarget: ObjectNode.ValueMapperCommandwith fields:sourcePointer: String(JSON Pointer, e.g.,/person/firstName)targetPointer: String(e.g.,/name/given)transformations: List<ValueMapperTransformation>?(optional)
ValueMapperTransformation(abstract):canTransform(node: JsonNode): Booleantransform(value: Any): Pair<Boolean, Any?>→didSkipand result
CopyTransformation(when: Any, then: Any? = null, skipCondition: String? = null)- Active when the source value equals
when(after JSON→Kotlin conversion). - Sets
thenas the result, otherwise the original value. skipConditionis a SpEL expression; when true, this command is skipped.
- Active when the source value equals
TypeTransformation(whenType: JsonNodeType, thenType: String)- Active when
node.nodeType == whenType. - Converts the value to
thenType(class name, e.g.,java.lang.String).
- Active when
{
"commands": [
{
"sourcePointer": "/person/firstName",
"targetPointer": "/name/given"
}
]
}{
"commands": [
{
"sourcePointer": "/status",
"targetPointer": "/state",
"transformations": [
{
"type": "CopyTransformation",
"when": "active",
"then": "enabled",
"skipCondition": "it == null"
}
]
}
]
}- If source is
null→ skip. - If source is "active" → write "enabled".
{
"commands": [
{
"sourcePointer": "/amount",
"targetPointer": "/amountAsText",
"transformations": [
{
"type": "TypeTransformation",
"whenType": "NUMBER",
"thenType": "java.lang.String"
}
]
}
]
}{
"commands": [
{
"sourcePointer": "/status",
"targetPointer": "/state",
"defaultValue": "UNKNOWN"
}
]
}- Template syntax:
${ ... }. - Variable
itcontains the current source value. - Examples:
it == null,it > 100. - Expressions are evaluated against a context map that exposes
sourceValue,targetValue,inputNode, andoutputNode, so both command-level and transformation-level conditions can inspect the current draft of the output and the source node. - Defining
skipConditionon a command lets you short-circuit the entire command before any transformations execute; when the expression returnstrue, nothing is written to the target. - COPY command
Transformationinstances may keep their ownskipCondition; if it evaluates totruethe transformation returnsnullregardless of initially matching the sourcePoitner value, and the command can still populate the target if adefaultValueis supplied.
targetPointer == "/"→ error (root cannot be overwritten).- Source path doesn’t exist or no transformation matches → command is logged as skipped.
- Array transformation →
ValueMapperMappingException.
CopyTransformation(with SpEL-basedskipCondition) andTypeTransformation.- Clear semantics:
nulltransformation list copies; empty list skips. - SpEL
skipConditioncan now live on the command level, allowing commands to be skipped before any transformations run. - COPY commands honor
defaultValueeven when transformations are absent or skipped, so you can emit fallback data without adding a transformation.