我有以下示例格式的巨大 json 。我想过滤 "d1"等于 "St"的所有项目。我也想删除该对象,以防由于上述过滤而没有留下任何项目。
[
{
"containertype": "check2",
"item": [
{
"d1": "St"
},
{
"d1": "Pt"
},
{
"d1": "St"
}
],
"contenttype": "test"
},
{
"containertype": "check2",
"item": [
{
"d1": "St"
},
{
"d1": "St"
},
{
"d1": "st"
}
],
"contenttype": "test"
}
]
预期结果
[
{
"containertype": "check2",
"item": [
{
"d1": "Pt"
}
],
"contenttype": "test"
}
]
这是我尝试过的,我正在读取json,使用Gson,我现在得到了 map ,我正在尝试过滤满足条件的项目。 :
public class Testing {
public static void main(String[] args) {
try {
final String json = "[{"containertype":"check2","item":[{"d1":"St"},{"d1":"Pt"},{"d1":"St"}],"contenttype":"test"},{"containertype":"check2","item":[{"d1":"Pt"},{"d1":"Pt"},{"d1":"Pt"}],"contenttype":"test"}]";
Gson gson = new Gson();
Type rowListType = new TypeToken<List<Map<String, Object>>>() {
}.getType();
final List<Map<String, Object>> rows = gson.fromJson(json, rowListType);
rows.stream()
.filter(r -> r.containsKey("item"))
.collect(Collectors.toList());
System.out.println(gson.toJson(rows, rowListType));
} catch (Exception e) {
e.printStackTrace();
}
}
}
最佳答案
定义一些POJO类
JSON 旨在读取/反序列化为某些对象。因此,Gson(或者 jackson )被称为映射器。他们将 JSON 映射到 POJO(普通的旧 Java 对象)。
那么让我们定义模型。 为了简单起见,使用了 Lombok(构造函数、getter/setter、toString)。
项目
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
public class Item {
private String d1;
}
容器(包含元素)
另外使用 Gson 的注释来遵守 Java 命名约定(camelCase),同时允许您指定的字段名称(小写)。
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
public class Container {
@SerializedName("containertype")
private String containerType;
@SerializedName("item")
private List<Item> items;
@SerializedName("contenttype")
private String contentType;
}
向服务类添加功能
将一些 JSON 映射到容器
使用类型引用让 Gson 知道要创建哪些对象。
Type containerListType = new TypeToken<ArrayList<Container>>(){}.getType();
gson = new Gson();
List<Container> containerList = gson.fromJson(json, containerListType);
过滤掉包含符合指定条件的项目的容器
使用函数谓词和流(Java 8):
public static Predicate<Item> itemWhereD1equalsSt = item -> "St".equals(item.getD1());
public static Predicate<Container> containerHasItemsWhereD1equalsSt = container -> {
List<Item> items = container.getItems();
if (items != null) {
boolean hasItemMatching = items.stream().anyMatch(itemWhereD1equalsSt);
return hasItemMatching;
}
return false;
};
public List<Container> filterFromJson(List<Container> containerList, Predicate<Container> containerPredicate) {
return containerList.stream()
.filter(containerPredicate)
.collect(Collectors.toList());
}
删除符合指定条件的项目
在列表上使用基于流和功能便捷方法(Java 8):
(a) 简单变体(使用 lambda 表达式内联谓词):
public void removeItemsSimple(List<Container> containers) {
for (Container container : containers) {
container.getItems().removeIf(item -> item.getD1().equalsIgnoreCase("St"));
}
}
(b) 增强的变体(将谓词作为参数传递,我们已经在容器中使用):
public List<Item> removeItemsBasedOnFilter(List<Container> containers, Predicate<Item> itemPredicate) {
return containers.stream()
.flatMap(container -> removeItemsBasedOnFilter(container, itemPredicate).stream())
.collect(Collectors.toList());
}
public List<Item> removeItemsBasedOnFilter(Container container, Predicate<Item> itemPredicate) {
// Optional: filter all items in container that should be removed
List<Item> itemsToBeRemoved = container.getItems().stream()
.filter(itemPredicate)
.collect(Collectors.toList());
// remove all items that match the predicate
container.getItems().removeIf(itemPredicate);
// Optional: return removed items
return itemsToBeRemoved;
}
完整的服务等级
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class JsonFilter {
private static final Type containerListType = new TypeToken<ArrayList<Container>>(){}.getType();
public static Predicate<Item> itemWhereD1equalsSt = item -> "St".equals(item.getD1());
public static Predicate<Container> containerHasItemsWhereD1equalsSt = container -> {
List<Item> items = container.getItems();
if (items != null) {
boolean hasItemMatching = items.stream().anyMatch(itemWhereD1equalsSt);
return hasItemMatching;
}
return false;
};
private final Gson gson;
public JsonFilter() {
gson = new Gson();
}
public List<Container> readContainers(String json) {
List<Container> containerList = gson.fromJson(json, containerListType);
return containerList;
}
public List<Container> filterFromJson(List<Container> containerList, Predicate<Container> containerPredicate) {
return containerList.stream()
.filter(containerPredicate)
.collect(Collectors.toList());
}
public void removeItemsSimple(List<Container> containers) {
for (Container container : containers) {
container.getItems().removeIf(item -> item.getD1().equalsIgnoreCase("St"));
}
}
public List<Item> removeItemsBasedOnFilter(List<Container> containers, Predicate<Item> itemPredicate) {
return containers.stream()
.flatMap(container -> removeItemsBasedOnFilter(container, itemPredicate).stream())
.collect(Collectors.toList());
}
public List<Item> removeItemsBasedOnFilter(Container container, Predicate<Item> itemPredicate) {
// Optional: filter all items in container that should be removed
List<Item> itemsToBeRemoved = container.getItems().stream()
.filter(itemPredicate)
.collect(Collectors.toList());
// remove all items that match the predicate
container.getItems().removeIf(itemPredicate);
// Optional: return removed items
return itemsToBeRemoved;
}
}
已测试
使用没有断言的JUnit5 - 只需打印到控制台。
import org.junit.jupiter.api.Test;
import java.util.List;
class JsonFilterTest {
@Test
void filterContainerList() {
final String json = givenJson(); // your test-data
final JsonFilter jsonFilter = new JsonFilter();
// map JSON to a list of containers
List<Container> containersRead = jsonFilter.readContainers(json);
// first filter-out all containers that do not have specified items
List<Container> containersFiltered = jsonFilter.filterFromJson(containersRead, JsonFilter.containerHasItemsWhereD1equalsSt);
System.out.println("Filtered containers resulting: " + containersFiltered.size());
// then remove specified items from these resulting containers
List<Item> itemsRemoved = jsonFilter.removeItemsBasedOnFilter(containersFiltered, JsonFilter.itemWhereD1equalsSt);
System.out.println("Removed items: " + itemsRemoved.size());
}
private String givenJson() {
return "[\n" +
" {\n" +
" \"containertype\": \"check2\",\n" +
" \"item\": [\n" +
" {\n" +
" \"d1\": \"St\"\n" +
" },\n" +
" {\n" +
" \"d1\": \"Pt\"\n" +
" },\n" +
" {\n" +
" \"d1\": \"St\"\n" +
" }\n" +
" ],\n" +
" \"contenttype\": \"test\"\n" +
" },\n" +
" {\n" +
" \"containertype\": \"check2\",\n" +
" \"item\": [\n" +
" {\n" +
" \"d1\": \"Pt\"\n" +
" },\n" +
" {\n" +
" \"d1\": \"Pt\"\n" +
" },\n" +
" {\n" +
" \"d1\": \"Pt\"\n" +
" }\n" +
" ],\n" +
" \"contenttype\": \"test\"\n" +
" }\n" +
"]";
}
}
关于java - 使用 GSON 和 lambda 过滤 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61057908/