Skip to content

Commit de10903

Browse files
committed
String functions
1 parent 1e6c2a6 commit de10903

File tree

7 files changed

+127
-1
lines changed

7 files changed

+127
-1
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package dev.vepo.jsonata.functions;
2+
3+
import dev.vepo.jsonata.functions.data.Data;
4+
import dev.vepo.jsonata.functions.json.JsonFactory;
5+
6+
public record LengthJSONataFunction(JSONataFunction provider) implements JSONataFunction {
7+
8+
@Override
9+
public Data map(Data original, Data current) {
10+
return JsonFactory.numberValue(provider.map(original, current).toJson().asText().length());
11+
}
12+
13+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package dev.vepo.jsonata.functions;
2+
3+
import dev.vepo.jsonata.functions.data.Data;
4+
import dev.vepo.jsonata.functions.json.JsonFactory;
5+
6+
public record StringCastJSONataFunction(JSONataFunction provider) implements JSONataFunction {
7+
@Override
8+
public Data map(Data original, Data current) {
9+
return JsonFactory.stringValue(provider.map(original, current).toJson().asText());
10+
}
11+
12+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package dev.vepo.jsonata.functions;
2+
3+
import java.util.List;
4+
5+
import dev.vepo.jsonata.functions.data.Data;
6+
import dev.vepo.jsonata.functions.json.JsonFactory;
7+
8+
public record SubstringAfterJSONataFunction(List<JSONataFunction> valueProviders) implements JSONataFunction {
9+
public SubstringAfterJSONataFunction {
10+
if (valueProviders.size() != 2) {
11+
throw new IllegalArgumentException("SubstringAfter function must have 2 arguments");
12+
}
13+
}
14+
15+
@Override
16+
public Data map(Data original, Data current) {
17+
var value = valueProviders.get(0).map(original, current).toJson().asText();
18+
var pattern = valueProviders.get(1).map(original, current).toJson().asText();
19+
return JsonFactory.stringValue(value.substring(value.indexOf(pattern) + pattern.length()));
20+
}
21+
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package dev.vepo.jsonata.functions;
2+
3+
import java.util.List;
4+
5+
import dev.vepo.jsonata.functions.data.Data;
6+
import dev.vepo.jsonata.functions.json.JsonFactory;
7+
8+
public record SubstringBeforeJSONataFunction(List<JSONataFunction> valueProviders) implements JSONataFunction {
9+
public SubstringBeforeJSONataFunction {
10+
if (valueProviders.size() != 2) {
11+
throw new IllegalArgumentException("SubstringBefore function must have 2 arguments");
12+
}
13+
}
14+
15+
@Override
16+
public Data map(Data original, Data current) {
17+
var value = valueProviders.get(0).map(original, current).toJson().asText();
18+
var pattern = valueProviders.get(1).map(original, current).toJson().asText();
19+
return JsonFactory.stringValue(value.substring(0, value.indexOf(pattern)));
20+
}
21+
22+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package dev.vepo.jsonata.functions;
2+
3+
import java.util.List;
4+
5+
import dev.vepo.jsonata.functions.data.Data;
6+
import dev.vepo.jsonata.functions.json.JsonFactory;
7+
8+
public record SubstringJSONataFunction(List<JSONataFunction> providers) implements JSONataFunction {
9+
public SubstringJSONataFunction {
10+
if (providers.size() < 2 || providers.size() > 3) {
11+
throw new IllegalArgumentException("Substring function must have 2 or 3 parameters");
12+
}
13+
}
14+
15+
@Override
16+
public Data map(Data original, Data current) {
17+
if (providers.size() == 2) {
18+
return JsonFactory.stringValue(providers.get(0).map(original, current).toJson().asText()
19+
.substring(providers.get(1).map(original, current).toJson().asInt()));
20+
} else {
21+
return JsonFactory.stringValue(providers.get(0).map(original, current).toJson().asText()
22+
.substring(providers.get(1).map(original, current).toJson().asInt(),
23+
providers.get(2).map(original, current).toJson().asInt()));
24+
}
25+
}
26+
27+
}

src/main/java/dev/vepo/jsonata/parser/JSONataGrammarListener.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,14 @@
4242
import dev.vepo.jsonata.functions.InlineIfJSONataFunction;
4343
import dev.vepo.jsonata.functions.JSONataFunction;
4444
import dev.vepo.jsonata.functions.JoinJSONataFunction;
45+
import dev.vepo.jsonata.functions.LengthJSONataFunction;
4546
import dev.vepo.jsonata.functions.ObjectBuilderJSONataFunction;
4647
import dev.vepo.jsonata.functions.ObjectMapperJSONataFunction;
48+
import dev.vepo.jsonata.functions.StringCastJSONataFunction;
4749
import dev.vepo.jsonata.functions.StringConcatJSONataFunction;
50+
import dev.vepo.jsonata.functions.SubstringAfterJSONataFunction;
51+
import dev.vepo.jsonata.functions.SubstringBeforeJSONataFunction;
52+
import dev.vepo.jsonata.functions.SubstringJSONataFunction;
4853
import dev.vepo.jsonata.functions.UserDefinedFunctionJSONataFunction;
4954
import dev.vepo.jsonata.functions.WildcardJSONataFunction;
5055
import dev.vepo.jsonata.functions.generated.JSONataGrammarBaseListener;
@@ -83,7 +88,12 @@
8388
public class JSONataGrammarListener extends JSONataGrammarBaseListener {
8489
public enum BuiltInFunction {
8590
SORT("$sort"),
86-
SUM("$sum");
91+
SUM("$sum"),
92+
STRING("$string"),
93+
LENGTH("$length"),
94+
SUBSTRING("$substring"),
95+
SUBSTRINGBEFORE("$substringBefore"),
96+
SUBSTRINGAFTER("$substringAfter");
8797

8898
public static Optional<BuiltInFunction> get(String name) {
8999
return Stream.of(values())
@@ -154,6 +164,12 @@ public void exitFunctionCall(FunctionCallContext ctx) {
154164
.map(fn -> switch (fn) {
155165
case SORT -> new BuiltInSortJSONataFunction(expressions.removeLast(), maybeFn);
156166
case SUM -> new BuiltInSumJSONataFunction(expressions.removeLast());
167+
case STRING -> new StringCastJSONataFunction(expressions.removeLast());
168+
case LENGTH -> new LengthJSONataFunction(expressions.removeLast());
169+
case SUBSTRING -> new SubstringJSONataFunction(previous(ctx.functionStatement().parameterStatement().size()));
170+
case SUBSTRINGBEFORE -> new SubstringBeforeJSONataFunction(previous(ctx.functionStatement().parameterStatement()
171+
.size()));
172+
case SUBSTRINGAFTER -> new SubstringAfterJSONataFunction(previous(ctx.functionStatement().parameterStatement().size()));
157173
})
158174
.orElseGet(() -> this.blocks.peek().function(fnName)
159175
.map(fn -> new UserDefinedFunctionJSONataFunction(previous(fn.parameterNames().size()),

src/test/java/dev/vepo/jsonata/JSONataTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,20 @@ void literalTest() {
261261

262262
@Nested
263263
class Functions {
264+
@Test
265+
void stringTest() {
266+
assertThat(jsonata("$string(5)").evaluate("{}").asText()).isEqualTo("5");
267+
assertThat(jsonata("$length(\"0123456789\")").evaluate("{}").asText()).isEqualTo("10");
268+
}
269+
270+
@Test
271+
void substringTest() {
272+
assertThat(jsonata("$substring(\"abcdef\",2)").evaluate("{}").asText()).isEqualTo("cdef");
273+
assertThat(jsonata("$substring(\"abcdef\",2,4)").evaluate("{}").asText()).isEqualTo("cd");
274+
assertThat(jsonata("$substringBefore(\"abcdef\", \"c\")").evaluate("{}").asText()).isEqualTo("ab");
275+
assertThat(jsonata("$substringAfter(\"abcdef\", \"c\")").evaluate("{}").asText()).isEqualTo("def");
276+
}
277+
264278
@Test
265279
void sortTest() {
266280
assertThat(jsonata("""

0 commit comments

Comments
 (0)