在Java中高效地将Json拆分为多个Json字符串

时间:2019-07-29 10:59:12

标签: java json jackson

我有一个json字符串,如下所示,我想将其拆分/分解为多个json字符串。

输入:

{
    "name": "paddy",
    "age": 29,
    "cities": [
        {
            "cityName": "Chennai",
            "year": "2013-2015"
        },
        {
            "cityName": "Bangalore",
            "year": "2015-2019"
        }
    ]
}

我想转换成两个Json字符串

json 1

{
    "name": "paddy",
    "age": 29,
    "cities": [
        {
            "cityName": "Chennai",
            "year": "2013-2015"
        }
        ]
}

json 2

{
    "name": "paddy",
    "age": 29,
    "cities": [
        {
            "cityName": "Bangalore",
            "year": "2015-2019"
        }
    ]
}

到目前为止,我下面的方法是使用杰克逊库。

package com.test;

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 java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class JsonParser {

  public static void main(String[] args) throws IOException {

    String json =
        "{\n"
            + "\t\"name\": \"paddy\",\n"
            + "\t\"age\": 29,\n"
            + "\t\"cities\": [\n"
            + "\t\t{\n"
            + "\t\t\t\"cityName\": \"Chennai\",\n"
            + "\t\t\t\"year\": \"2013-2015\"\n"
            + "\t\t},\n"
            + "\t\t{\n"
            + "\t\t\t\"cityName\": \"Bangalore\",\n"
            + "\t\t\t\"year\": \"2015-2019\"\n"
            + "\t\t}\n"
            + "\t]\n"
            + "}";

    ObjectMapper mapper = new ObjectMapper();
    mapper.enable(SerializationFeature.INDENT_OUTPUT);

// Create a list to store the result (the list will store Jackson tree model objects)
    List<JsonNode> result = new ArrayList<>();


    JsonNode tree = mapper.readTree(json);
    JsonNode paths = tree.get("cities");
    Iterator<JsonNode> elements = paths.elements();

    while (elements.hasNext()) {


      JsonNode path = elements.next();


      // Create a copy of the tree
      JsonNode copyOfTree = mapper.valueToTree(tree);
      ((ArrayNode)copyOfTree.get("cities")).removeAll().add(path);


      // Add the modified tree to the result list
      result.add(copyOfTree);
    }

// Print the result
    for (JsonNode node : result) {
      System.out.println(mapper.writeValueAsString(node));
      System.out.println();
    }
  }
}

如果json较小,则上述方法可以正常工作。有没有更好的方法来处理大型json文件。例如,假设“城市”有百万个对象。

谢谢。

1 个答案:

答案 0 :(得分:1)

您需要考虑许多不同的因素。首先,不要复制整个根对象。如果您有一个大的cities数组,那么您只会浪费内存来创建新副本并从中删除所有元素。参见以下示例:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.File;
import java.io.IOException;

public class JsonApp {

  public static void main(String[] args) throws IOException {
    File jsonFile = new File("./spring-basics/src/main/resources/test.json");

    ObjectMapper mapper = new ObjectMapper();

    // read whole JSON
    ObjectNode root = (ObjectNode) mapper.readTree(jsonFile);
    String citiesFieldName = "cities";

    // remove cities from root, now it contains only common properties
    ArrayNode cities = (ArrayNode) root.remove(citiesFieldName);
    cities.elements().forEachRemaining(item -> {
      // copy root
      ObjectNode copyOfRoot = root.deepCopy();
      // add one city to copy
      copyOfRoot.set(citiesFieldName, copyOfRoot.arrayNode().add(item));

      // add to result or send further
      System.out.println(copyOfRoot);
    });
  }
}

以上代码复制root并将一个元素添加到cities数组中。现在,我们需要考虑如何处理结果。您可以立即将其发送以进行下一步处理,也可以存储在列表中,然后以批量操作发送。另一个改进可以是将cities数组拆分为更大的块(超过1个元素)。请参阅this article,了解如何拆分列表。例如,如果您有1_000_000个元素,请在1_000个元素块列表中进行拆分。