【问题标题】:How to parse json in Spring Boot and write to a repository如何在 Spring Boot 中解析 json 并写入存储库
【发布时间】:2019-03-06 21:27:33
【问题描述】:

我正在尝试解析可能包含数千行的历史时间序列数据的 JSON API 响应。响应格式如下:

{
    "name": "AAPL",
    "history": {
        "2019-03-05": {
            "open": "175.94",
            "close": "175.53",
            "high": "176.00",
            "low": "174.54",
            "volume": "19163899"
        },
        "2019-03-04": {
            "open": "175.69",
            "close": "175.85",
            "high": "177.75",
            "low": "173.97",
            "volume": "27436203"
        }
    }
} 

我想将响应写入 Spring 存储库。我有一个简单的代码来执行此操作,下面显示了一个部分:

RestTemplate restTemplate = new RestTemplate();
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject) jsonParser.parse(result);
JsonElement jsonElement = jsonObject.get("history");
Set<Map.Entry<String, JsonElement>> entrySet = jsonElement.getAsJsonObject().entrySet();

for (Map.Entry<String, JsonElement> entry : entrySet) {
    StockHistory stockHistory = new StockHistory();
    stockHistory.setSymbol(stk);
    // .... Other code
}

我根据 JSON 响应设置对象属性,将对象添加到列表中,最后将列表保存到存储库。这个过程可能非常缓慢,因为我正在为 JSON 返回中的每个元素创建一个新的 StockHistory 对象。我想知道是否有更好的方法。

【问题讨论】:

  • 能否请您检查更新后的答案并告诉我是否有帮助?谢谢。 :)

标签: java json spring spring-boot


【解决方案1】:

因为您无法修改 JSON 结构。我想添加以下代码,它可以解析您在名为Repo 的简单类中提供的 JSON。为此,您需要使用我使用过的add the library from here

现在您需要在代码中添加以下类。

public class Repo {
    public String name;
    public ArrayList<History> histories;

    public Repo() {
        histories = new ArrayList<History>();
    }
}

public class History {
    public String date;
    public HistoryElements elements;
}

public class HistoryElements {
    public String volume;
    public String high;
    public String low;
    public String close;
    public String open;
}

因此我编写了RepoParser 并使用您的 JSON 字符串对其进行了测试,并将 JSON 解析为类。

import com.oracle.javafx.jmx.json.JSONException;
import org.json.JSONObject;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Iterator;

public class RepoParser {
    public static Repo parseRepo(String jsonString) throws ParseException, JSONException {

        JSONObject jsonObject = new JSONObject(jsonString);
        Iterator<?> iterator = jsonObject.keys();
        Repo repo = new Repo();

        while (iterator.hasNext()) {
            String obj = iterator.next().toString();

            if (obj.equals("name")) repo.name = obj;
            else repo.histories = parseHistory((JSONObject) jsonObject.get(obj));
        }

        return repo;
    }

    public static ArrayList<History> parseHistory(JSONObject jsonObject) throws ParseException, JSONException {
        Iterator<?> iterator = jsonObject.keys();
        ArrayList<History> historyList = new ArrayList<>();

        while (iterator.hasNext()) {
            String obj = iterator.next().toString();
            History history = new History();
            history.date = obj;
            history.elements = parseHistoryElement((JSONObject) jsonObject.get(obj));

            historyList.add(history);
        }

        return historyList;
    }

    public static HistoryElements parseHistoryElement(JSONObject jsonObject) throws ParseException, JSONException {
        Iterator<?> iterator = jsonObject.keys();
        HistoryElements historyElements = new HistoryElements();

        while (iterator.hasNext()) {
            String obj = iterator.next().toString();

            if (obj.equals("open")) historyElements.open = jsonObject.getString("open");
            if (obj.equals("close")) historyElements.close = jsonObject.getString("close");
            if (obj.equals("high")) historyElements.high = jsonObject.getString("high");
            if (obj.equals("low")) historyElements.low = jsonObject.getString("low");
            if (obj.equals("volume")) historyElements.volume = jsonObject.getString("volume");
        }

        return historyElements;
    }
}

只需使用RepoParser 类,如下所示。

try {
    Repo repo = RepoParser.parseRepo(jsonString);
} catch (Exception e) {
    e.printStackTrace();
}

为了方便,我也有created a Gist

更新

您可以考虑将所有Repo 添加到一个列表中,然后使用存储库的save 方法一次将它们全部保存到您的数据库中。

因此代码应该如下所示。

try {
    while(there is no repo left for parsing) {
        Repo repo = RepoParser.parseRepo(jsonString);
        repoList.add(repo)
    }

    yourRepository.save(repoList); // Save all values at once

} catch (Exception e) {
    e.printStackTrace();
}

希望对您有所帮助!

【讨论】:

  • 我不确定我是否理解建议的类结构。 json 响应中的日期每天都可以追溯到 20 年。请解释一下。
  • 我已经更新了我的答案。你能调查一下吗?
  • 我无法控制 Json 文件。我正在使用来自互联网数据提供商的 REST API。
  • 我不想挑剔,但是这个public class 2019-03-04 不是Java中类的有效命名。
  • @makasu,我已经更新了我的答案,可以解析你的 JSON 字符串。您能否尝试在您的代码中添加我建议并提供链接的库?然后,您需要在添加我上面编写的类后尝试我的解析器。如果有问题,请告诉我。我已经测试了我身边的代码,它工作得很好。谢谢:)
【解决方案2】:

经过一番研究,我发现问题出在hibernate上。据我了解,hibernate的一个有用的特性是它缓存对象,但是当为插入创建大量对象时,这会导致问题。该问题可以通过使用 spring.jpa.properties.hibernate.jdbc.batch_size 属性的批处理和在实体类中使用序列生成器来解决。现在保存数千行的列表要快得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 2018-06-29
    • 2018-09-23
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多