mirror of
https://gitee.com/dromara/hutool.git
synced 2026-02-09 09:16:26 +08:00
add jsonpath enhance
This commit is contained in:
@@ -838,30 +838,30 @@ public class CollUtil {
|
||||
/**
|
||||
* 截取列表的部分
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 被截取的数组
|
||||
* @param start 开始位置(包含)
|
||||
* @param end 结束位置(不包含)
|
||||
* @param step 步进
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 被截取的数组
|
||||
* @param startInclude 开始位置(包含)
|
||||
* @param endExclude 结束位置(不包含)
|
||||
* @param step 步进
|
||||
* @return 截取后的数组,当开始位置超过最大时,返回空的List
|
||||
* @see ListUtil#sub(List, int, int, int)
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static <T> List<T> sub(final List<T> list, final int start, final int end, final int step) {
|
||||
return ListUtil.sub(list, start, end, step);
|
||||
public static <T> List<T> sub(final List<T> list, final int startInclude, final int endExclude, final int step) {
|
||||
return ListUtil.sub(list, startInclude, endExclude, step);
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取集合的部分
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param collection 被截取的数组
|
||||
* @param start 开始位置(包含)
|
||||
* @param end 结束位置(不包含)
|
||||
* @param <T> 集合元素类型
|
||||
* @param collection 被截取的数组
|
||||
* @param startInclude 开始位置(包含)
|
||||
* @param endExclude 结束位置(不包含)
|
||||
* @return 截取后的数组,当开始位置超过最大时,返回null
|
||||
*/
|
||||
public static <T> List<T> sub(final Collection<T> collection, final int start, final int end) {
|
||||
return sub(collection, start, end, 1);
|
||||
public static <T> List<T> sub(final Collection<T> collection, final int startInclude, final int endExclude) {
|
||||
return sub(collection, startInclude, endExclude, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -869,19 +869,19 @@ public class CollUtil {
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param collection 被截取的数组
|
||||
* @param start 开始位置(包含)
|
||||
* @param end 结束位置(不包含)
|
||||
* @param startInclude 开始位置(包含)
|
||||
* @param endExclude 结束位置(不包含)
|
||||
* @param step 步进
|
||||
* @return 截取后的数组,当开始位置超过最大时,返回空集合
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static <T> List<T> sub(final Collection<T> collection, final int start, final int end, final int step) {
|
||||
public static <T> List<T> sub(final Collection<T> collection, final int startInclude, final int endExclude, final int step) {
|
||||
if (isEmpty(collection)) {
|
||||
return ListUtil.empty();
|
||||
}
|
||||
|
||||
final List<T> list = collection instanceof List ? (List<T>) collection : ListUtil.of(collection);
|
||||
return sub(list, start, end, step);
|
||||
return sub(list, startInclude, endExclude, step);
|
||||
}
|
||||
// endregion
|
||||
|
||||
@@ -1399,12 +1399,12 @@ public class CollUtil {
|
||||
* 将两个列表的元素按照索引一一配对,通过指定的函数进行合并,返回一个新的结果列表。
|
||||
* 新列表的长度将以两个输入列表中较短的那个为准。
|
||||
*
|
||||
* @param <A> 第一个列表的元素类型
|
||||
* @param <B> 第二个列表的元素类型
|
||||
* @param <R> 结果列表的元素类型
|
||||
* @param collectionA 第一个列表
|
||||
* @param collectionB 第二个列表
|
||||
* @param zipper 合并函数,接收来自listA和listB的两个元素,返回一个结果元素
|
||||
* @param <A> 第一个列表的元素类型
|
||||
* @param <B> 第二个列表的元素类型
|
||||
* @param <R> 结果列表的元素类型
|
||||
* @param collectionA 第一个列表
|
||||
* @param collectionB 第二个列表
|
||||
* @param zipper 合并函数,接收来自listA和listB的两个元素,返回一个结果元素
|
||||
* @return 合并后的新列表
|
||||
* @since 5.8.42
|
||||
*/
|
||||
@@ -1419,7 +1419,7 @@ public class CollUtil {
|
||||
final Iterator<A> aIterator = collectionA.iterator();
|
||||
final Iterator<B> bIterator = collectionB.iterator();
|
||||
|
||||
while(size-- > 0) {
|
||||
while (size-- > 0) {
|
||||
result.add(zipper.apply(aIterator.next(), bIterator.next()));
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -27,6 +27,7 @@ import cn.hutool.v7.core.comparator.PropertyComparator;
|
||||
import cn.hutool.v7.core.lang.Assert;
|
||||
import cn.hutool.v7.core.lang.Validator;
|
||||
import cn.hutool.v7.core.lang.page.PageInfo;
|
||||
import cn.hutool.v7.core.reflect.ConstructorUtil;
|
||||
import cn.hutool.v7.core.util.ObjUtil;
|
||||
|
||||
import java.util.*;
|
||||
@@ -114,8 +115,8 @@ public class ListUtil {
|
||||
* 新建一个List<br>
|
||||
* 提供的参数为null时返回空{@link ArrayList}
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param isLinked 是否新建LinkedList
|
||||
* @param <T> 集合元素类型
|
||||
* @param isLinked 是否新建LinkedList
|
||||
* @param enumeration {@link Enumeration}
|
||||
* @return ArrayList对象
|
||||
* @since 3.0.8
|
||||
@@ -238,12 +239,12 @@ public class ListUtil {
|
||||
/**
|
||||
* 获取一个只包含一个元素的List,不可变
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @param <T> 元素类型
|
||||
* @param element 元素
|
||||
* @return 只包含一个元素的List
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static <T> List<T> singleton(final T element){
|
||||
public static <T> List<T> singleton(final T element) {
|
||||
return Collections.singletonList(element);
|
||||
}
|
||||
|
||||
@@ -497,12 +498,12 @@ public class ListUtil {
|
||||
/**
|
||||
* 在指定位置设置元素。当index小于List的长度时,替换指定位置的值,否则追加{@code paddingElement}直到到达index后,设置值
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @param list List列表
|
||||
* @param index 位置
|
||||
* @param element 新元素
|
||||
* @param <T> 元素类型
|
||||
* @param list List列表
|
||||
* @param index 位置
|
||||
* @param element 新元素
|
||||
* @param paddingElement 填充的值
|
||||
* @param indexLimit 最大索引限制
|
||||
* @param indexLimit 最大索引限制
|
||||
* @return 原List
|
||||
* @since 5.8.28
|
||||
*/
|
||||
@@ -512,7 +513,7 @@ public class ListUtil {
|
||||
if (index < size) {
|
||||
list.set(index, element);
|
||||
} else {
|
||||
if(indexLimit > 0){
|
||||
if (indexLimit > 0) {
|
||||
// issue#3286, 增加安全检查
|
||||
Validator.checkIndexLimit(index, indexLimit);
|
||||
}
|
||||
@@ -541,41 +542,47 @@ public class ListUtil {
|
||||
* 截取集合的部分<br>
|
||||
* 此方法与{@link List#subList(int, int)} 不同在于子列表是新的副本,操作子列表不会影响原列表。
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 被截取的数组
|
||||
* @param begionInclude 开始位置(包含)
|
||||
* @param endExclude 结束位置(不包含)
|
||||
* @param step 步进
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 被截取的数组
|
||||
* @param startInclude 开始位置(包含)
|
||||
* @param endExclude 结束位置(不包含)
|
||||
* @param step 步进
|
||||
* @return 截取后的数组,当开始位置超过最大时,返回空的List
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static <T> List<T> sub(final List<T> list, int begionInclude, int endExclude, int step) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> List<T> sub(final List<T> list, int startInclude, int endExclude, int step) {
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<T> result = ConstructorUtil.newInstanceIfPossible(list.getClass());
|
||||
if (null == result) {
|
||||
result = new ArrayList<>(0);
|
||||
}
|
||||
|
||||
if (list.isEmpty()) {
|
||||
return new ArrayList<>(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
final int size = list.size();
|
||||
if (begionInclude < 0) {
|
||||
begionInclude += size;
|
||||
if (startInclude < 0) {
|
||||
startInclude += size;
|
||||
}
|
||||
if (endExclude < 0) {
|
||||
endExclude += size;
|
||||
}
|
||||
if (begionInclude == size) {
|
||||
return new ArrayList<>(0);
|
||||
if (startInclude == size) {
|
||||
return result;
|
||||
}
|
||||
if (begionInclude > endExclude) {
|
||||
final int tmp = begionInclude;
|
||||
begionInclude = endExclude;
|
||||
if (startInclude > endExclude) {
|
||||
final int tmp = startInclude;
|
||||
startInclude = endExclude;
|
||||
endExclude = tmp;
|
||||
}
|
||||
if (endExclude > size) {
|
||||
if (begionInclude >= size) {
|
||||
return new ArrayList<>(0);
|
||||
if (startInclude >= size) {
|
||||
return result;
|
||||
}
|
||||
endExclude = size;
|
||||
}
|
||||
@@ -584,8 +591,7 @@ public class ListUtil {
|
||||
step = 1;
|
||||
}
|
||||
|
||||
final List<T> result = new ArrayList<>();
|
||||
for (int i = begionInclude; i < endExclude; i += step) {
|
||||
for (int i = startInclude; i < endExclude; i += step) {
|
||||
result.add(list.get(i));
|
||||
}
|
||||
return result;
|
||||
@@ -630,7 +636,7 @@ public class ListUtil {
|
||||
* @return 分段列表
|
||||
* @since 5.4.5
|
||||
*/
|
||||
public static <T> List<List<T>> partition(final List<T> list, final int size) {
|
||||
public static <T> List<List<T>> partition(final List<T> list, final int size) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return empty();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ package cn.hutool.v7.core.pool;
|
||||
|
||||
/**
|
||||
* 对象工厂接口,用于自定义对象创建、验证和销毁<br>
|
||||
* 来自:https://github.com/DanielYWoo/fast-object-pool/
|
||||
* 来自:<a href="https://github.com/DanielYWoo/fast-object-pool/">fast-object-pool</a>
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
* @author Daniel
|
||||
|
||||
@@ -22,6 +22,7 @@ import cn.hutool.v7.core.lang.Validator;
|
||||
import cn.hutool.v7.core.lang.mutable.MutableEntry;
|
||||
import cn.hutool.v7.json.serializer.impl.ArrayTypeAdapter;
|
||||
import cn.hutool.v7.json.serializer.impl.IterTypeAdapter;
|
||||
import cn.hutool.v7.json.support.InternalJSONUtil;
|
||||
import cn.hutool.v7.json.writer.JSONWriter;
|
||||
|
||||
import java.io.Serial;
|
||||
@@ -117,6 +118,7 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
}
|
||||
|
||||
// region ----- addValue
|
||||
|
||||
/**
|
||||
* 加入{@code null}元素,如果设置中忽略null值,则忽略
|
||||
*
|
||||
@@ -255,7 +257,7 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
|
||||
// 越界则追加到指定位置
|
||||
final int size = size();
|
||||
if(index == size){
|
||||
if (index == size) {
|
||||
add(element);
|
||||
return null;
|
||||
}
|
||||
@@ -331,6 +333,18 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
return (List<T>) IterTypeAdapter.INSTANCE.deserialize(this, ArrayList.class, elementType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取子JSONArray,不修改原JSONArray,生成新的JSONArray
|
||||
*
|
||||
* @param startInclude 起始位置,包含此位置
|
||||
* @param endExclude 结束位置,不包含此位置
|
||||
* @param step 步长,默认为1
|
||||
* @return 截取后的JSONArray对象,如果原始数组为空则返回一个空的JSONArray
|
||||
*/
|
||||
public JSONArray sub(final int startInclude, final int endExclude, final int step) {
|
||||
return InternalJSONUtil.sub(this, startInclude, endExclude, step);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为JSON字符串,无缩进
|
||||
*
|
||||
|
||||
@@ -25,6 +25,7 @@ import cn.hutool.v7.core.text.CharUtil;
|
||||
import cn.hutool.v7.core.text.StrUtil;
|
||||
import cn.hutool.v7.core.util.ObjUtil;
|
||||
import cn.hutool.v7.json.JSON;
|
||||
import cn.hutool.v7.json.JSONArray;
|
||||
import cn.hutool.v7.json.JSONConfig;
|
||||
import cn.hutool.v7.json.JSONFactory;
|
||||
import cn.hutool.v7.json.serializer.JSONMapper;
|
||||
@@ -206,6 +207,58 @@ public final class InternalJSONUtil {
|
||||
return rawHashMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据给定的JSONArray,截取子数组,包含startInclude,不包含endExclude
|
||||
*
|
||||
* @param jsonArray JSONArray 对象
|
||||
* @param startInclude 起始位置,包含此位置
|
||||
* @param endExclude 结束位置,不包含此位置
|
||||
* @param step 步长,默认为1
|
||||
* @return 截取后的JSONArray对象,如果原始数组为空则返回一个空的JSONArray
|
||||
*/
|
||||
public static JSONArray sub(final JSONArray jsonArray, int startInclude, int endExclude, int step) {
|
||||
if (jsonArray == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (jsonArray.isEmpty()) {
|
||||
return new JSONArray(0, jsonArray.getFactory());
|
||||
}
|
||||
|
||||
final int size = jsonArray.size();
|
||||
if (startInclude < 0) {
|
||||
startInclude += size;
|
||||
}
|
||||
if (endExclude < 0) {
|
||||
endExclude += size;
|
||||
}
|
||||
if (startInclude == size) {
|
||||
return new JSONArray(0, jsonArray.getFactory());
|
||||
}
|
||||
if (startInclude > endExclude) {
|
||||
final int tmp = startInclude;
|
||||
startInclude = endExclude;
|
||||
endExclude = tmp;
|
||||
}
|
||||
if (endExclude > size) {
|
||||
if (startInclude >= size) {
|
||||
return new JSONArray(0, jsonArray.getFactory());
|
||||
}
|
||||
endExclude = size;
|
||||
}
|
||||
|
||||
if (step < 1) {
|
||||
step = 1;
|
||||
}
|
||||
|
||||
final int resultLength = (int) Math.ceil((endExclude - startInclude) / (double) step);
|
||||
final JSONArray result = new JSONArray(resultLength, jsonArray.getFactory());
|
||||
for (int i = startInclude; i < endExclude; i += step) {
|
||||
result.add(jsonArray.get(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package cn.hutool.v7.json.support;
|
||||
|
||||
import cn.hutool.v7.json.JSON;
|
||||
import cn.hutool.v7.json.JSONArray;
|
||||
import cn.hutool.v7.json.JSONFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collector;
|
||||
|
||||
/**
|
||||
* JSONArray Collector
|
||||
*
|
||||
* @author Looly
|
||||
* @since 7.0.0
|
||||
*/
|
||||
public class JSONArrayCollector implements Collector<JSON, JSONArray, JSONArray> {
|
||||
|
||||
/**
|
||||
* 返回一个Collector,它将输入元素收集到一个新的JSONArray中
|
||||
*
|
||||
* @param factory JSON 工厂
|
||||
* @return {@link JSONArrayCollector}
|
||||
*/
|
||||
public static JSONArrayCollector toJSONArray(final JSONFactory factory) {
|
||||
return new JSONArrayCollector(factory);
|
||||
}
|
||||
|
||||
private final JSONFactory factory;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param factory JSON 工厂
|
||||
*/
|
||||
public JSONArrayCollector(final JSONFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Supplier<JSONArray> supplier() {
|
||||
return this.factory::ofArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiConsumer<JSONArray, JSON> accumulator() {
|
||||
return JSONArray::addValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryOperator<JSONArray> combiner() {
|
||||
return (left, right) -> {
|
||||
left.addAll(right);
|
||||
return left;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<JSONArray, JSONArray> finisher() {
|
||||
return Function.identity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Characteristics> characteristics() {
|
||||
return Collections.unmodifiableSet(EnumSet.of(
|
||||
Characteristics.IDENTITY_FINISH,
|
||||
Characteristics.CONCURRENT
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,23 @@ public class JSONNodeBeanFactory implements NodeBeanFactory<JSON> {
|
||||
if (bean instanceof JSONObject) {
|
||||
return ((JSONObject) bean).get(name);
|
||||
} else if (bean instanceof JSONArray) {
|
||||
return ((JSONArray) bean).get(Integer.parseInt(name));
|
||||
if("*".equals(name)){
|
||||
// issue#IDC78B@Gitee 支持数组的*取值
|
||||
return bean;
|
||||
}
|
||||
try{
|
||||
final int index = Integer.parseInt(name);
|
||||
// 数字返回对应的下标元素
|
||||
return ((JSONArray) bean).get(index);
|
||||
} catch(final NumberFormatException e){
|
||||
// 非数字,则认为是key,返回JSONArray中每个元素key对应的value
|
||||
return ((JSONArray) bean).stream().map(jsonEle -> {
|
||||
if(jsonEle instanceof JSONObject){
|
||||
return ((JSONObject) jsonEle).get(name);
|
||||
}
|
||||
throw new UnsupportedOperationException("Can not get by name for: " + jsonEle.getClass());
|
||||
}).collect(JSONArrayCollector.toJSONArray(bean.getFactory()));
|
||||
}
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Can not get by name for: " + bean.getClass());
|
||||
@@ -143,7 +159,7 @@ public class JSONNodeBeanFactory implements NodeBeanFactory<JSON> {
|
||||
*/
|
||||
private Object getValueByRangeNode(final JSON bean, final RangeNode node) {
|
||||
if (bean instanceof JSONArray) {
|
||||
return CollUtil.sub((JSONArray) bean, node.getStart(), node.getEnd(), node.getStep());
|
||||
return ((JSONArray) bean).sub(node.getStart(), node.getEnd(), node.getStep());
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Can not get range value for: " + bean.getClass());
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
package cn.hutool.v7.json;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
|
||||
/**
|
||||
* JSON路径单元测试
|
||||
*
|
||||
@@ -31,9 +33,9 @@ public class JSONPathTest {
|
||||
public void getByPathTest() {
|
||||
final String json = "[{\"id\":\"1\",\"name\":\"xingming\"},{\"id\":\"2\",\"name\":\"mingzi\"}]";
|
||||
Object value = JSONUtil.parseArray(json).getByPath("[0].name", Object.class);
|
||||
Assertions.assertEquals("xingming", value);
|
||||
assertEquals("xingming", value);
|
||||
value = JSONUtil.parseArray(json).getByPath("[1].name", Object.class);
|
||||
Assertions.assertEquals("mingzi", value);
|
||||
assertEquals("mingzi", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -41,6 +43,21 @@ public class JSONPathTest {
|
||||
final String str = "{'accountId':111}";
|
||||
final JSON json = JSONUtil.parse(str);
|
||||
final Long accountId = JSONUtil.getByPath(json, "$.accountId", 0L);
|
||||
Assertions.assertEquals(111L, accountId.longValue());
|
||||
assertEquals(111L, accountId.longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void issueIDC78BTest() {
|
||||
final String json = "{\"actionMessage\":{\"alertResults\":[],\"decodeFeas\":[{\"body\":{\"lats\":[{\"begin\":4260,\"text\":\"呵呵\"},{\"begin\":4260,\"text\":\"你好 \"}]}}]}}";
|
||||
final JSON json1 = JSONUtil.parse(json);
|
||||
final JSON byPath = json1.getByPath("$.actionMessage.decodeFeas[0].body.lats[*]");
|
||||
assertInstanceOf(JSONArray.class, byPath);
|
||||
assertEquals(2, byPath.size());
|
||||
|
||||
final JSON byPath2 = json1.getByPath("$.actionMessage.decodeFeas[0].body.lats[*].text");
|
||||
assertInstanceOf(JSONArray.class, byPath2);
|
||||
assertEquals(2, byPath2.size());
|
||||
assertEquals("呵呵", byPath2.asJSONArray().getStr(0));
|
||||
assertEquals("你好 ", byPath2.asJSONArray().getStr(1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
package cn.hutool.v7.json.support;
|
||||
|
||||
import cn.hutool.v7.json.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class JSONArrayCollectorTest {
|
||||
|
||||
private final JSONFactory factory = JSONFactory.of(JSONConfig.of());
|
||||
|
||||
@Test
|
||||
void testSupplier() {
|
||||
final JSONArrayCollector collector = new JSONArrayCollector(factory);
|
||||
final JSONArray array = collector.supplier().get();
|
||||
assertTrue(array.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAccumulator() {
|
||||
final JSONArrayCollector collector = new JSONArrayCollector(factory);
|
||||
final JSONArray array = collector.supplier().get();
|
||||
final JSONObject obj = factory.ofObj();
|
||||
obj.putValue("key", "value");
|
||||
|
||||
collector.accumulator().accept(array, obj);
|
||||
assertEquals(1, array.size());
|
||||
assertEquals(obj, array.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCombiner() {
|
||||
final JSONArrayCollector collector = new JSONArrayCollector(factory);
|
||||
final JSONArray left = factory.ofArray();
|
||||
final JSONArray right = factory.ofArray();
|
||||
|
||||
final JSONObject obj1 = factory.ofObj();
|
||||
obj1.putValue("key1", "value1");
|
||||
left.add(obj1);
|
||||
|
||||
final JSONObject obj2 = factory.ofObj();
|
||||
obj2.putValue("key2", "value2");
|
||||
right.add(obj2);
|
||||
|
||||
final JSONArray combined = collector.combiner().apply(left, right);
|
||||
assertEquals(2, combined.size());
|
||||
assertEquals(obj1, combined.get(0));
|
||||
assertEquals(obj2, combined.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFinisher() {
|
||||
final JSONArrayCollector collector = new JSONArrayCollector(factory);
|
||||
final JSONArray array = factory.ofArray();
|
||||
final JSONArray result = collector.finisher().apply(array);
|
||||
assertSame(array, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCharacteristics() {
|
||||
final JSONArrayCollector collector = new JSONArrayCollector(factory);
|
||||
final Set<Collector.Characteristics> characteristics = collector.characteristics();
|
||||
assertEquals(2, characteristics.size());
|
||||
assertTrue(characteristics.contains(Collector.Characteristics.IDENTITY_FINISH));
|
||||
assertTrue(characteristics.contains(Collector.Characteristics.CONCURRENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFullCollectionProcess() {
|
||||
final JSONObject obj1 = factory.ofObj();
|
||||
obj1.putValue("key1", "value1");
|
||||
final JSONObject obj2 = factory.ofObj();
|
||||
obj2.putValue("key2", "value2");
|
||||
|
||||
final JSONArray result = Stream.of(obj1, obj2)
|
||||
.collect(JSONArrayCollector.toJSONArray(factory));
|
||||
|
||||
assertEquals(2, result.size());
|
||||
assertEquals(obj1, result.get(0));
|
||||
assertEquals(obj2, result.get(1));
|
||||
}
|
||||
|
||||
@SuppressWarnings("RedundantOperationOnEmptyContainer")
|
||||
@Test
|
||||
void testEmptyCollection() {
|
||||
final JSONArray result = Collections.<JSON>emptyList().stream()
|
||||
.collect(JSONArrayCollector.toJSONArray(factory));
|
||||
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user