Repository navigation
[2.0.0] — 2026-10-02
pyjolt now behaves exactly like the reference Java JOLT implementation. It
passes all 178 cases of the reference project's own test suite (shift,
default, remove, cardinality, sort, all three modify flavours and chained
transforms), which runs in CI as tests/conformance. A spec built on the
JOLT demo site now gives the same output in
pyjolt. Before this release, 35 of those cases passed.
Every transform was rebuilt on a port of the reference path-matching engine.
The public API (Chainr, Shift(spec).apply(data), …) is unchanged, but
some 1.x behaviour that differed from JOLT has changed — see Upgrading below.
Added
ModifyDefine/modify-define-beta: write only where a key does not
exist.- Shift:
@and@(n,path)as spec keys (use input values as keys, e.g.
turn[{"name": k, "value": v}]into{k: v}),&in spec keys,\
escaping of special characters,[#n]and[@(n,path)]array indexes,
""to write to the output root. - Default:
a|bkeys, andkey[]for arrays (including a top-level
array input). - Modify: all reference functions (
isPresent,notNull,isNull,
squashDuplicates,sort,divide,divideAndRound,intSubtract, …),
+/~/_per-key mode prefixes,?"only if present" suffix,[n]
array indexes,^pathcontext lookups, and custom functions via
ModifyOverwrite(spec, functions={...}).pyjolt.MISSINGis exported for
custom functions that produce no value. - Chainr:
apply(data, context=...), and JOLT's Java class names
(com.bazaarvoice.jolt.Shiftr, …) as operation names. - Remove:
a|bkeys, multiple*in a key, removing array indexes. - Sort: keys starting with
~sort first, as in JOLT. - A reference-conformance test suite (
tests/conformance).
Changed — upgrading from 1.x
[]always appends a new element. In 1.x,"out[].a"and"out[].b"
written under the same*match were grouped into one object; that was a
pyjolt-only behaviour. Write to a shared index instead:
"out[&1].a","out[&1].b".- Shift returns
Nonewhen nothing matches (1.x returned{}). - Function arguments.
"=fn"still appliesfnto the current value, but
"=fn(args)"now uses only the given arguments, as in JOLT. 1.x passed the
current value as a hidden first argument. Reference the current value with
@(1,key):"=concat(@(1,name),'-x')","=min(@(1,n),10)",
"=split(',',@(1,s))". Thesplitseparator is a regular expression. - Function results follow JOLT. For example
=toBooleanonly converts
"true"/"false",=toIntegeron3.7gives3, and a function that
can't produce a value leaves the field unchanged. - Unknown modify functions emit a
UserWarningand produce no value, so a
list of alternatives falls through to the next one (1.x raisedSpecError). - Default on arrays requires JOLT's
key[]syntax:
{"items[]": {"*": {...}}}. A plain{"items": {"*": {...}}}no longer
reaches into a list, and a top-level list input needs a"*"or index spec. - Cardinality:
MANYturnsnullinto[](1.x gave[null]).
ONE/MANYare case-sensitive. - Invalid specs are rejected as in JOLT: an empty
{}spec for shift or
cardinality,#in a shift output path, or array indexes mixed with object
keys in a modify spec raiseSpecError. - Modify uses JOLT's function names
=toUpper/=toLower; the 1.x names
=toUpperCase/=toLowerCasestill work. The other 1.x-only functions
(toFloat,floatSum,sum,sqrt,not,coalesce,startsWith,
endsWith,contains,indexOf) remain available, with JOLT-style
arguments.
Notes
- Transforms still never modify the input you pass in.
Chainrnow copies the
input once instead of once per step. - The engine does more work per key than 1.x did; expect roughly 1.4× the
runtime of 1.2.2 on large inputs.