Browse Source

feat: add join func

pull/976/head
lhy 5 months ago
parent
commit
2032b74d31
  1. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java
  2. 166
      json-path/src/main/java/com/jayway/jsonpath/internal/function/text/Join.java
  3. 13
      json-path/src/test/java/com/jayway/jsonpath/internal/function/JSONEntityPathFunctionTest.java

2
json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java

@ -12,6 +12,7 @@ import com.jayway.jsonpath.internal.function.sequence.First;
import com.jayway.jsonpath.internal.function.sequence.Index;
import com.jayway.jsonpath.internal.function.sequence.Last;
import com.jayway.jsonpath.internal.function.text.Concatenate;
import com.jayway.jsonpath.internal.function.text.Join;
import com.jayway.jsonpath.internal.function.text.Length;
import java.util.Collections;
@ -43,6 +44,7 @@ public class PathFunctionFactory {
// Text Functions
map.put("concat", Concatenate.class);
map.put("join", Join.class);
// JSON Entity Functions
map.put(Length.TOKEN_NAME, Length.class);

166
json-path/src/main/java/com/jayway/jsonpath/internal/function/text/Join.java

@ -0,0 +1,166 @@
package com.jayway.jsonpath.internal.function.text;
import com.jayway.jsonpath.internal.EvaluationContext;
import com.jayway.jsonpath.internal.PathRef;
import com.jayway.jsonpath.internal.function.ParamType;
import com.jayway.jsonpath.internal.function.Parameter;
import com.jayway.jsonpath.internal.function.PathFunction;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* join values in an array, supply two grammars:
* <p>
* 1. [].join([delimiter],[..path])
* 2. $.join([delimiter],[..path])
*/
public class Join implements PathFunction {
@Override
public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {
String delimiter = this.getDelimiterFromParameters(parameters);
Collection<String> results = Collections.emptyList();
// [].join([..path])
if (ctx.configuration().jsonProvider().isArray(model)) {
results = this.joinByArrayModel(model, ctx, parameters);
}
// $.join([delimiter],[..path])
if (null == results || results.size() == 0) {
results = this.joinByParams(ctx, parameters);
}
if (null == results || results.size() == 0) {
return "";
}
return String.join(delimiter, results);
}
/**
* get results by model
*
* @param model
* @param ctx
* @param parameters
* @return
*/
protected Collection<String> joinByArrayModel(Object model, EvaluationContext ctx, List<Parameter> parameters) {
Collection<String> resultList = new ArrayList<>();
List<Parameter> pathParams = Optional.ofNullable(parameters).orElseGet(Collections::emptyList)
.stream().filter(item -> ParamType.PATH.equals(item.getType())).collect(Collectors.toList());
if (pathParams.size() == 0) {
return this.arrayIterableToList(ctx, model, item -> null);
}
for (Parameter pathParam : pathParams) {
List<String> list = this.arrayIterableToList(ctx, model, item -> {
Object value = pathParam.getPath().evaluate(item, model, ctx.configuration()).getValue();
return this.arrayIterableToList(ctx, value, obj -> null);
});
if (null == list || list.size() == 0) {
continue;
}
resultList.addAll(list);
}
return resultList;
}
/**
* get results by params
*
* @param ctx
* @param parameters
* @return
*/
protected Collection<String> joinByParams(EvaluationContext ctx, List<Parameter> parameters) {
if (null == parameters || parameters.size() == 0) {
return null;
}
List<Parameter> notJsonParams = parameters.stream().filter(item -> ParamType.PATH.equals(item.getType())).collect(Collectors.toList());
if (notJsonParams.size() == 0) {
return parameters.stream().map(Parameter::getValue).filter(Objects::nonNull).map(Object::toString).collect(Collectors.toList());
}
List<String> list = Parameter.toList(String.class, ctx, notJsonParams);
return list.size() > 0 ? list : null;
}
/**
* get delimiter
*
* @param parameters
* @return
*/
protected String getDelimiterFromParameters(List<Parameter> parameters) {
if (null != parameters && parameters.size() >= 1) {
Parameter parameter = parameters.get(0);
if (ParamType.JSON.equals(parameter.getType())) {
return parameter.getValue().toString();
}
}
return ",";
}
/**
* literal quantity type
*
* @param obj
* @return
*/
protected boolean simpleType(Object obj) {
if (null == obj) {
return false;
}
return obj instanceof Number || obj instanceof CharSequence ||
obj instanceof Boolean || obj instanceof Character;
}
/**
* iterable
*
* @param ctx
* @param model
* @param itemIsNotSimpleFunc
*/
protected List<String> arrayIterableToList(EvaluationContext ctx, Object model, Function<Object, List<String>> itemIsNotSimpleFunc) {
if (null == model) {
return Collections.emptyList();
}
if (this.simpleType(model)) {
return Collections.singletonList(model.toString());
}
boolean isArray = ctx.configuration().jsonProvider().isArray(model);
if (!isArray) {
return Collections.emptyList();
}
List<String> resultList = new ArrayList<>();
Iterable<?> iterable = ctx.configuration().jsonProvider().toIterable(model);
for (Object obj : iterable) {
if (null == obj) {
continue;
}
boolean isSimpleType = this.simpleType(obj);
if (isSimpleType) {
resultList.add(obj.toString());
continue;
}
List<String> items = itemIsNotSimpleFunc.apply(obj);
if (null == items || items.size() == 0) {
continue;
}
resultList.addAll(items);
}
return resultList;
}
}

13
json-path/src/test/java/com/jayway/jsonpath/internal/function/JSONEntityPathFunctionTest.java

@ -2,6 +2,7 @@ package com.jayway.jsonpath.internal.function;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Configurations;
import com.jayway.jsonpath.Option;
import net.minidev.json.JSONArray;
import org.junit.Test;
@ -106,4 +107,16 @@ public class JSONEntityPathFunctionTest extends BaseFunctionTest {
verifyFunction(conf, path, BATCH_JSON, values);
}
@Test
public void testParameterJoinFunctionCall() {
Configuration configuration = Configuration.builder().options(Option.DEFAULT_PATH_LEAF_TO_NULL, Option.SUPPRESS_EXCEPTIONS).build();
verifyFunction(configuration, "$.text.join()", TEXT_SERIES, "a,b,c,d,e,f");
verifyFunction(configuration, "$.text.join(\"|\")", TEXT_SERIES, "a|b|c|d|e|f");
verifyFunction(configuration, "$.join($.batches.results[*].productId)", BATCH_JSON, "23,23");
verifyFunction(configuration, "$.join(\" _ \",$.batches.results[*].values[?(@ > 10)])", BATCH_JSON, "45 _ 34 _ 23 _ 52 _ 12 _ 11 _ 18 _ 22");
verifyFunction(configuration, "$.join(\" \",$.batches.results[*].values[?(@ < 10)], $.batches.results[*].productId)", BATCH_JSON, "2 3 5 4 3 2 1 3 1 23 23");
verifyFunction(configuration, "$.batches.results.join(\" \", $.productId, $.values[?(@ < 10)])", BATCH_JSON, "23 23 2 3 5 4 3 2 1 3 1");
}
}

Loading…
Cancel
Save