简体   繁体   English

如何在Spring Boot中解析json并写入存储库

[英]How to parse json in Spring Boot and write to a repository

I am trying to parse a JSON API response of historical time series data with potentially thousands of line. 我正在尝试使用可能的数千行来解析历史时间序列数据的JSON API响应。 The response is in the following format: 响应采用以下格式:

{
    "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"
        }
    }
} 

I would like to write the response to a Spring repository. 我想将响应写到Spring存储库。 I have a simple code to do this and a section is shown below: 我有一个简单的代码可以做到这一点,下面显示了一个部分:

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
}

I set the object properties as per JSON response, add the object to a list, and finally save the list to a repository. 我根据JSON响应设置对象属性,将对象添加到列表中,最后将列表保存到存储库中。 This process is very slow presumably because I am creating a new StockHistory object for every element in the JSON return. 据推测,此过程非常缓慢,因为我正在为JSON返回中的每个元素创建一个新的StockHistory对象。 I was wondering if there is a better way of doing it. 我想知道是否有更好的方法。

As you cannot modify the JSON structure. 由于您无法修改JSON结构。 I would like to add the following code that can parse the JSON that you provided in a simple class called Repo . 我想添加以下代码,这些代码可以解析您在名为Repo的简单类中提供的JSON。 In order to do that you need to add the library from here that I have used. 为此,您需要从这里使用我添加的库

Now you need to add the following classes in your code. 现在,您需要在代码中添加以下类。

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

Hence I have written a RepoParser and tested it with your JSON String and it parses the JSON into the classes. 因此,我编写了一个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;
    }
}

Just use the RepoParser class like the following. 只需使用RepoParser类,如下所示。

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

I have created a Gist as well for convenience. 为方便起见,我也创建了一个Gist

Update 更新资料

You might consider adding all the Repo in a list and then save all of them into your database at once using the save method of the repository. 您可能会考虑将所有的Repo列表中,然后所有的人都保存到数据库中一次使用save库的方法。

Hence the code should be something like the following. 因此,代码应类似于以下内容。

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();
}

Hope that helps! 希望有帮助!

After some research, I found that the problem was with hibernate. 经过研究,我发现问题出在休眠状态。 As far as I understand it, a useful feature of hibernate is that it caches objects, but this causes a problem when a large number of objects are created for insertion. 据我了解,hibernate的一个有用功能是它可以缓存对象,但是当创建大量用于插入的对象时,这会引起问题。 The issue can be resolved by batch processing using the spring.jpa.properties.hibernate.jdbc.batch_size property and using a sequence generator in the entity class. 可以通过使用spring.jpa.properties.hibernate.jdbc.batch_size属性并在实体类中使用序列生成器进行批处理来解决此问题。 Now saving the list of many thousands of lines is much faster. 现在保存成千上万行的列表要快得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM