So entfernen Sie Schlüsselwertpaare aus einer JSON-Datei in Java
Ich habe mich gefragt, ob mir jemand helfen oder mir einen Hinweis geben kann, wie die angehängte Dummy-JSON-Datei in Java bearbeitet werden kann.
Wie Sie sehen können, habe ich ein Kopfobjekt, das viele Werte und untergeordnete Elemente enthält, die demselben Muster folgen.
Ich wollte wissen, ob es eine Möglichkeit gibt, alle Schlüssel zu entfernen, bei denen der Wert -1 ist.

Folgendes habe ich anhand vieler Websites versucht 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());
//
Der obige Code zeigt die Struktur der Datei an. Mein Problem besteht jedoch darin, die -1-Werte in den untergeordneten Elementen zu erreichen und sie zu entfernen.
Mit den Methoden .getClass und .simpleName weiß ich, dass es sich um eine ArrayList handelt, bin aber verwirrt, wie ich sie durchsuchen soll.
Jede Hilfe wird sehr geschätzt!
Antworten
In können Jackson
Sie die gesamte JSON
Nutzlast als lesen JsonNode
und über alle Eigenschaften iterieren, um die gegebene Bedingung zu überprüfen. Wenn die Bedingung erfüllt ist, können Sie das angegebene Feld entfernen. Dazu müssen Sie eine rekursive Methode implementieren . Schauen Sie sich das folgende Beispiel an:
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);
}
}
}
Für unter JSON
Nutzlast:
{
"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
}
]
}
]
}
obiger Code druckt:
{
"name" : "Head",
"children" : [ {
"name" : "project1",
"children" : [ {
"name" : "project1",
"missed" : 10,
"covered" : 11
} ]
}, {
"name" : "project1",
"covered" : 12,
"children" : [ {
"name" : "project1",
"missed" : 10
} ]
} ]
}
Siehe auch:
- Reduzieren einer verschachtelten JSON-Zeichenfolge mit drei Ebenen in Java
Es gibt zwei Haupttechniken zum Parsen und Generieren von JSON-Daten (sowie viele andere Formate wie XML usw.): Objektzuordnung und ereignis- / token- / streamorientierte Verarbeitung. Der zweite Weg ist der beste Weg für viele Fälle, einschließlich Filterung. Requisiten:
- Die Datei / Daten müssen nicht vollständig in den Speicher geladen werden. Sie können Megs / Gigs problemlos verarbeiten
- Es funktioniert viel schneller, insbesondere bei großen Dateien
- Mit diesem Muster ist es einfach, einen benutzerdefinierten Typ / eine benutzerdefinierte Transformationsregel zu implementieren
Sowohl Gson als auch Jackson unterstützen die Stream-orientierte Verarbeitung. Die Idee hier zu veranschaulichen ist nur ein Beispiel mit einem winzigen Parser / Generatorhttps://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
}
}
}