Java의 JSON 파일에서 키 값 쌍을 제거하는 방법

Dec 03 2020

누구든지 나를 도와 줄 수 있는지 또는 첨부 된 더미 JSON 파일을 Java로 편집하는 방법에 대해 힌트를 줄 수 있는지 궁금합니다.

보시다시피 동일한 패턴을 따르는 많은 값과 자식을 포함하는 헤드 개체가 있습니다.

값이 -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라는 것을 알고 있지만 검색 방법에 대해서는 혼란 스럽습니다.

어떤 도움이라도 대단히 감사하겠습니다!

답변

1 MichałZiober Dec 04 2020 at 00:49

에서 Jackson전체 JSON페이로드를 읽고 JsonNode주어진 조건을 모든 속성 검사에 대해 반복 할 수 있습니다 . 조건이 충족되면 주어진 필드를 제거 할 수 있습니다. 그렇게하려면 재귀 메서드 를 구현해야합니다 . 아래 예를 살펴보십시오.

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
    } ]
  } ]
}

또한보십시오:

  • 자바에서 3 단계 중첩 JSON 문자열 병합
2 AnatolyG Dec 03 2020 at 11:09

JSON 데이터를 구문 분석하고 생성하는 두 가지 주요 기술 (XML과 같은 다른 형식 포함)이 있습니다. 객체 매핑과 이벤트 / 토큰 / 스트림 지향 처리입니다. 두 번째 방법은 필터링을 포함하여 많은 경우에 가장 좋은 방법입니다. 소품:

  • 파일 / 데이터를 완전히 메모리에로드 할 필요가 없습니다. 문제없이 megs / gigs를 처리 할 수 ​​있습니다.
  • 특히 대용량 파일의 경우 훨씬 더 빠르게 작동합니다.
  • 이 패턴으로 사용자 정의 유형 / 변환 규칙을 쉽게 구현할 수 있습니다.

Gson과 Jackson은 모두 스트림 지향 처리를 지원합니다. 여기에 아이디어를 설명하기 위해 작은 파서 / 생성기를 사용하는 예가 있습니다.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
        }
    }
}