如何从 java 中的 JSON 文件中删除键值对
How to remove key value pairs from a JSON file in java
我想知道是否有人可以帮助我或提示我如何编辑 Java 中附加的虚拟 JSON 文件。
如您所见,我有一个 head 对象,其中包含许多值和遵循相同模式的子项。
我想知道是否有办法删除所有值为 -1 的键。
以下是我根据许多使用 jackson
的网站尝试的结果:
try {
// create object mapper instance
ObjectMapper mapper = new ObjectMapper();
// convert JSON file to map
Map<?, ?> map = mapper.readValue(Paths.get("test.json").toFile(), Map.class);
// print map entries
for (Map.Entry<?, ?> entry : map.entrySet()) {
isInteger = main.isObjectInteger(entry.getValue());
// System.out.println("if value is all: " + entry.getKey() + "=" + entry.getValue());
//
上面的代码将显示文件的结构,但是我的问题是到达子项内部的 -1 值并删除它们。
使用 .getClass 和 .simpleName 方法我知道它是一个 arrayList 但我对如何搜索它感到困惑。
任何帮助将不胜感激!
有两种主要技术可以解析和生成 JSON 数据(以及许多其他格式,如 XML 等):对象映射和 event/token/stream-oriented 处理。第二种方式是许多情况下的最佳方式,包括过滤。道具:
- file/data 不需要完全加载到内存中,你
可以毫无问题地处理 megs/gigs
- 运行速度更快,尤其是对于大文件
- 使用此模式可以轻松实现任何自定义 type/rule 转换
Gson和Jackson都支持面向流的处理。为了说明这个想法,这里只是一个使用微小 parser/generator https://github.com/anatolygudkov/green-jelly
的例子
import org.green.jelly.AppendableWriter;
import org.green.jelly.JsonBufferedWriter;
import org.green.jelly.JsonEventPump;
import org.green.jelly.JsonNumber;
import org.green.jelly.JsonParser;
import java.io.StringWriter;
public class UpdateMyJson {
private static final String jsonToUpdate = "{\n" +
"\"name\": \"Head\",\n" +
"\"missed\": -1,\n" +
"\"children\": [\n" +
" {\n" +
" \"name\": \"project1\",\n" +
" \"fixes\": 0,\n" +
" \"commits\": -1,\n" +
" },\n" +
" {\n" +
" \"name\": \"project2\",\n" +
" \"fixes\": 20,\n" +
" \"commits\": 5,\n" +
" }\n" +
"]\n" +
"}";
public static void main(String[] args) {
final StringWriter result = new StringWriter(); // you can use FileWriter
final JsonParser parser = new JsonParser();
parser.setListener(new MyJsonUpdater(new AppendableWriter<>(result)));
parser.parseAndEoj(jsonToUpdate); // if you read a file with a buffer,
// to don't load the whole file into memory,
// call parse() several times (part by part) in a loop until EOF
// and then call .eoj()
System.out.println(result);
}
static class MyJsonUpdater extends JsonEventPump {
MyJsonUpdater(final JsonBufferedWriter output) {
super(output);
}
@Override
public boolean onNumberValue(final JsonNumber number) {
if (number.mantissa() == -1 && number.exp() == 0) {
return true; // return immediately
}
return super.onNumberValue(number); // otherwise pump the value to the result JSON
}
}
}
在 Jackson
中,您可以将整个 JSON
有效负载读取为 JsonNode
并遍历所有属性检查给定条件。如果满足条件,您可以删除给定的字段。为此,您需要实施 recursive method。看看下面的例子:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
public class JsonRemoveSomeFieldsApp {
public static void main(String[] args) throws IOException {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
JsonNode root = mapper.readTree(jsonFile);
JsonCleaner jsonCleaner = new JsonCleaner(root, (node) -> node.isNumber() && node.numberValue().intValue() == -1);
JsonNode result = jsonCleaner.removeAll();
// write to file
mapper.writeValue(System.out, result);
}
}
class JsonCleaner {
private final JsonNode root;
private final Predicate<JsonNode> toRemoveCondition;
JsonCleaner(JsonNode node, Predicate<JsonNode> toRemoveCondition) {
this.root = Objects.requireNonNull(node);
this.toRemoveCondition = Objects.requireNonNull(toRemoveCondition);
}
public JsonNode removeAll() {
process(root);
return root;
}
private void process(JsonNode node) {
if (node.isObject()) {
ObjectNode object = (ObjectNode) node;
Iterator<Map.Entry<String, JsonNode>> fields = object.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> field = fields.next();
JsonNode valueToCheck = field.getValue();
if (valueToCheck.isContainerNode()) {
process(valueToCheck);
} else if (toRemoveCondition.test(valueToCheck)) {
fields.remove();
}
}
} else if (node.isArray()) {
ArrayNode array = (ArrayNode) node;
array.elements().forEachRemaining(this::process);
}
}
}
对于以下 JSON
负载:
{
"name": "Head",
"missed": -1,
"covered": -1,
"children": [
{
"name": "project1",
"missed": -1,
"covered": -1,
"children": [
{
"name": "project1",
"missed": 10,
"covered": 11
}
]
},
{
"name": "project1",
"missed": -1,
"covered": 12,
"children": [
{
"name": "project1",
"missed": 10,
"covered": -1
}
]
}
]
}
以上代码打印:
{
"name" : "Head",
"children" : [ {
"name" : "project1",
"children" : [ {
"name" : "project1",
"missed" : 10,
"covered" : 11
} ]
}, {
"name" : "project1",
"covered" : 12,
"children" : [ {
"name" : "project1",
"missed" : 10
} ]
} ]
}
另请参阅:
我想知道是否有人可以帮助我或提示我如何编辑 Java 中附加的虚拟 JSON 文件。
如您所见,我有一个 head 对象,其中包含许多值和遵循相同模式的子项。
我想知道是否有办法删除所有值为 -1 的键。
以下是我根据许多使用 jackson
的网站尝试的结果:
try {
// create object mapper instance
ObjectMapper mapper = new ObjectMapper();
// convert JSON file to map
Map<?, ?> map = mapper.readValue(Paths.get("test.json").toFile(), Map.class);
// print map entries
for (Map.Entry<?, ?> entry : map.entrySet()) {
isInteger = main.isObjectInteger(entry.getValue());
// System.out.println("if value is all: " + entry.getKey() + "=" + entry.getValue());
//
上面的代码将显示文件的结构,但是我的问题是到达子项内部的 -1 值并删除它们。
使用 .getClass 和 .simpleName 方法我知道它是一个 arrayList 但我对如何搜索它感到困惑。
任何帮助将不胜感激!
有两种主要技术可以解析和生成 JSON 数据(以及许多其他格式,如 XML 等):对象映射和 event/token/stream-oriented 处理。第二种方式是许多情况下的最佳方式,包括过滤。道具:
- file/data 不需要完全加载到内存中,你 可以毫无问题地处理 megs/gigs
- 运行速度更快,尤其是对于大文件
- 使用此模式可以轻松实现任何自定义 type/rule 转换
Gson和Jackson都支持面向流的处理。为了说明这个想法,这里只是一个使用微小 parser/generator https://github.com/anatolygudkov/green-jelly
的例子import org.green.jelly.AppendableWriter;
import org.green.jelly.JsonBufferedWriter;
import org.green.jelly.JsonEventPump;
import org.green.jelly.JsonNumber;
import org.green.jelly.JsonParser;
import java.io.StringWriter;
public class UpdateMyJson {
private static final String jsonToUpdate = "{\n" +
"\"name\": \"Head\",\n" +
"\"missed\": -1,\n" +
"\"children\": [\n" +
" {\n" +
" \"name\": \"project1\",\n" +
" \"fixes\": 0,\n" +
" \"commits\": -1,\n" +
" },\n" +
" {\n" +
" \"name\": \"project2\",\n" +
" \"fixes\": 20,\n" +
" \"commits\": 5,\n" +
" }\n" +
"]\n" +
"}";
public static void main(String[] args) {
final StringWriter result = new StringWriter(); // you can use FileWriter
final JsonParser parser = new JsonParser();
parser.setListener(new MyJsonUpdater(new AppendableWriter<>(result)));
parser.parseAndEoj(jsonToUpdate); // if you read a file with a buffer,
// to don't load the whole file into memory,
// call parse() several times (part by part) in a loop until EOF
// and then call .eoj()
System.out.println(result);
}
static class MyJsonUpdater extends JsonEventPump {
MyJsonUpdater(final JsonBufferedWriter output) {
super(output);
}
@Override
public boolean onNumberValue(final JsonNumber number) {
if (number.mantissa() == -1 && number.exp() == 0) {
return true; // return immediately
}
return super.onNumberValue(number); // otherwise pump the value to the result JSON
}
}
}
在 Jackson
中,您可以将整个 JSON
有效负载读取为 JsonNode
并遍历所有属性检查给定条件。如果满足条件,您可以删除给定的字段。为此,您需要实施 recursive method。看看下面的例子:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
public class JsonRemoveSomeFieldsApp {
public static void main(String[] args) throws IOException {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
JsonNode root = mapper.readTree(jsonFile);
JsonCleaner jsonCleaner = new JsonCleaner(root, (node) -> node.isNumber() && node.numberValue().intValue() == -1);
JsonNode result = jsonCleaner.removeAll();
// write to file
mapper.writeValue(System.out, result);
}
}
class JsonCleaner {
private final JsonNode root;
private final Predicate<JsonNode> toRemoveCondition;
JsonCleaner(JsonNode node, Predicate<JsonNode> toRemoveCondition) {
this.root = Objects.requireNonNull(node);
this.toRemoveCondition = Objects.requireNonNull(toRemoveCondition);
}
public JsonNode removeAll() {
process(root);
return root;
}
private void process(JsonNode node) {
if (node.isObject()) {
ObjectNode object = (ObjectNode) node;
Iterator<Map.Entry<String, JsonNode>> fields = object.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> field = fields.next();
JsonNode valueToCheck = field.getValue();
if (valueToCheck.isContainerNode()) {
process(valueToCheck);
} else if (toRemoveCondition.test(valueToCheck)) {
fields.remove();
}
}
} else if (node.isArray()) {
ArrayNode array = (ArrayNode) node;
array.elements().forEachRemaining(this::process);
}
}
}
对于以下 JSON
负载:
{
"name": "Head",
"missed": -1,
"covered": -1,
"children": [
{
"name": "project1",
"missed": -1,
"covered": -1,
"children": [
{
"name": "project1",
"missed": 10,
"covered": 11
}
]
},
{
"name": "project1",
"missed": -1,
"covered": 12,
"children": [
{
"name": "project1",
"missed": 10,
"covered": -1
}
]
}
]
}
以上代码打印:
{
"name" : "Head",
"children" : [ {
"name" : "project1",
"children" : [ {
"name" : "project1",
"missed" : 10,
"covered" : 11
} ]
}, {
"name" : "project1",
"covered" : 12,
"children" : [ {
"name" : "project1",
"missed" : 10
} ]
} ]
}
另请参阅: