Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/main/java/com/dashjoin/jsonata/Jsonata.java
Original file line number Diff line number Diff line change
Expand Up @@ -2184,9 +2184,20 @@ public static class JFunction implements JFunctionCallable, JFunctionSignatureVa
Signature signature;
Method method;
Object methodInstance;
int numberOfArgs;

public JFunction(JFunctionCallable function, String signature) {
this(null, function, signature);
}

public JFunction(String functionName, JFunctionCallable function, String signature) {
this(functionName, function, signature, 0);
}

public JFunction(String functionName, JFunctionCallable function, String signature, int numberOfArgs) {
this.functionName = functionName;
this.function = function;
this.numberOfArgs = numberOfArgs;
if (signature!=null)
// use classname as default, gets overwritten once the function is registered
this.signature = new Signature(signature, function.getClass().getName());
Expand Down Expand Up @@ -2231,7 +2242,7 @@ public Object validate(Object args, Object context) {
}

public int getNumberOfArgs() {
return method != null ? method.getParameterTypes().length : 0;
return method != null ? method.getParameterTypes().length : numberOfArgs;
}
}

Expand Down
42 changes: 42 additions & 0 deletions src/test/java/com/dashjoin/jsonata/CustomFunctionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,48 @@ public Object call(Object input, List args) throws Throwable {
Assertions.assertEquals("abc", expression.evaluate(Map.of("a", "a", "b", "b", "c", "c")));
}

@Test
public void testFunctionWithInputData() {
JFunction addWithFactor = new JFunction("addWithFactor", (input, args) -> {
var inputMap = (Map<String, Object>)input;
String factor = inputMap.get("factor").toString();
int factorInt = Integer.parseInt(factor);
return ((Integer) args.get(0) + (Integer) args.get(1)) * factorInt;
}, null);

var expression = Jsonata.jsonata("$addWithFactor(1, 2)");
expression.registerFunction(addWithFactor.functionName, addWithFactor);
Assertions.assertEquals(9, expression.evaluate(Map.of("factor", "3")));
}

@Test
public void testFunctionWithInputData2() {
JFunction addWithFactor = new JFunction("multiply", (input, args) -> {
Object first = args.get(0);
Object second;
if (args.size() > 1) {
second = args.get(1);
} else {
var inputMap = (Map<String, Object>)input;
String factor = inputMap.get("factor").toString();
second = Integer.parseInt(factor);
}
return (Integer) first * (Integer) second;
}, null, 2);

var expression = Jsonata.jsonata("$multiply(3) ~> $multiply(?, 2)");
expression.registerFunction(addWithFactor.functionName, addWithFactor);
Assertions.assertEquals(18, expression.evaluate(Map.of("factor", "3")));
}

@Test
public void testCustomFunctionPipe() {
JFunction add = new JFunction("add", (input, args) -> (Integer) args.get(0) + (Integer) args.get(1), null, 2);
var expression = Jsonata.jsonata("$add(1, 2) ~> $add(?, 3)");
expression.registerFunction(add.functionName, add);
Assertions.assertEquals(6, expression.evaluate(null));
}

/**
* Lambdas use no signature - in case of an error, a ClassCastException is thrown
*/
Expand Down