Skip to content

Align $match with jsonata-js for undefined, empty and non-matching input - #457

Open
janedbal wants to merge 4 commits into
IBM:masterfrom
janedbal:fix-match-undefined-argument
Open

janedbal wants to merge 4 commits into
IBM:masterfrom
janedbal:fix-match-undefined-argument

Conversation

@janedbal

@janedbal janedbal commented Oct 5, 2026 •

Copy link
Copy Markdown

This PR aligns $match with jsonata-js for undefined, empty and non-matching input. The results below use jsonata-js 2.2.2 and JSONata4Java master. The input can be any value, e.g. {}.

1. Undefined str

Expression jsonata-js JSONata4Java (master)
$match(nothing, /b/) undefined Argument 1 of function $match does not match function signature
$match($substringAfter(nothing, "x"), /b/).groups[0] undefined same error
$match(nothing, /b/, -1) undefined same error
$match(nothing, /b/, "x") T0410, argument 3 same argument 1 error

2. Empty str

Expression jsonata-js JSONata4Java (master)
$match("", /^$/) {"match":"","index":0,"groups":[]} Argument 1 of function $match does not match function signature
$match("", /b/) undefined same error

3. No match

Expression jsonata-js JSONata4Java (master)
$match("abc", /z/) undefined []
{"m": $match("abc", /z/)} {} {"m":[]}
$exists($match("abc", /z/)) false true

References

  • jsonata-js match() in src/functions.js returns undefined first when str is undefined ("undefined inputs always return undefined"). It checks the limit value only after that. Signature validation still rejects a non-number limit.
  • The same function has no special case for an empty string. It returns this.createSequence(), which is undefined when nothing matches. docs/regex.md says that when nothing is matched, the result is "the empty sequence (i.e. JavaScript undefined)".
  • docs/simple.md says "No errors are thrown as a result of non-existing data in the input document."
  • $split, $replace and $match share the docs wording "It is an error if str is not a string". The test-suite cases function-split/case010, function-replace/case004 and function-contains/case004 expect undefined for nothing. JSONata4Java already returns undefined for those functions.

Related to #291. That issue shows the same error message for $match($.a, /(\d+)/), but its cause was the context-variable logic. Its repro already passes on master.

Fix

The fix is in MatchFunction, one commit per behavior:

  1. If str is undefined and the pattern is a regex, return undefined. A limit that is not a number still gives the argument 3 error.
  2. Accept an empty string as str.
  3. Return undefined when nothing matches. A limit of 0 already did this.

String patterns are a JSONata4Java extension, and jsonata-js rejects them. $match(nothing, 'b') still throws. A string pattern that does not match now also returns undefined, because both pattern kinds share the result code.

Changed existing test: $match('ababbabbcc','a(b+)') expected []. It checks that a string pattern matches literally. It now expects undefined. The equivalent jsonata-js expression $match("ababbabbcc", /a\(b\+\)/) also returns undefined.

Tests

I added these cases to MatchFunctionTests. The expected values come from jsonata-js 2.2.2:

  • undefined str: $match(a.b.c, /b/), $match(a.b.c, /b/, 1), $match(a.b.c, /b/, -1), $match($substringAfter(a.b.c, 'x'), /(b)/).groups[0], plus the argument 3 errors for 'x' and null
  • empty str: $match('', /^$/), $match('', /(x*)/), $match('', /b/)
  • no match: $match('abc', /z/), $match('abc', /z/, 1)

The default surefire includes (**/*Test.class) do not select *Tests classes. So I ran two commands on JDK 17:

  • mvn verify: 1223 tests, 0 failures. Master gives the same result.
  • mvn test -Dtest='com/api/jsonata4java/**/*Tests': 1977 tests, 0 failures. Master runs 1966 tests with 0 failures.

Co-Authored-By: Claude Code

— Claude

jsonata-js returns undefined from $match when its str argument is
undefined and the pattern is a regex. JSONata4Java threw "Argument 1
of function $match does not match function signature" instead.

Co-Authored-By: Claude Code
Signed-off-by: Jan Nedbal <jan.nedbal@shipmonk.com>
jsonata-js rejects a non-number limit (T0410, argument 3) also when
str is undefined. A negative limit still returns undefined, because
jsonata-js returns before it checks the limit value.

Co-Authored-By: Claude Code
Signed-off-by: Jan Nedbal <jan.nedbal@shipmonk.com>
jsonata-js applies the pattern to an empty string like to any other
string. For example, $match("", /^$/) returns one match at index 0.
JSONata4Java threw an argument 1 error instead.

Co-Authored-By: Claude Code
Signed-off-by: Jan Nedbal <jan.nedbal@shipmonk.com>
jsonata-js returns an empty sequence (undefined) when the pattern does
not match. JSONata4Java returned []. A limit of 0 already returned
undefined.

The existing test for $match('ababbabbcc','a(b+)') expected []. It
checks that a string pattern matches literally, so it now expects
undefined.

Co-Authored-By: Claude Code
Signed-off-by: Jan Nedbal <jan.nedbal@shipmonk.com>
@janedbal janedbal changed the title Return undefined from $match when str is undefined Align $match with jsonata-js for undefined, empty and non-matching input Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant