OutOfMemoryError when using Gson to parse a large JSON response

前端 未结 3 1114
深忆病人
深忆病人 2021-02-10 22:42
URL url = new URL(\"http://pubapi.cryptsy.com/api.php?method=orderdatav2\");
CryptsyCurrencyPairsReturn response = gson.fromJson(new InputStreamReader(url.openStream()),         


        
3条回答
  •  孤城傲影
    2021-02-10 22:53

    From my experience, you need to stream the JSON data.
    And yes you can use google GSON to stream JSON data this is an example how to do it :

    APIModel result = new APIModel();
            try {
                HttpResponse response;
                HttpClient myClient = new DefaultHttpClient();
                HttpPost myConnection = new HttpPost(APIParam.API_001_PRESENT(
                        serial_id, api_key));
                try {
                    response = myClient.execute(myConnection);
                    Reader streamReader = new InputStreamReader(response
                            .getEntity().getContent());
                    JsonReader reader = new JsonReader(streamReader);
                    reader.beginObject();
                    while (reader.hasNext()) {
    
                        String name = reader.nextName();
    
                        if (name.equals("result")) {
                            if (reader.nextString() == "NG") {
                                result.setResult(Util.API_001_RESULT_NG);
                                break;
                            }
                        } else if (name.equals("items")) {
                            result = readItemsArray(reader);
                        } else {
                            reader.skipValue(); // avoid some unhandle events
                        }
                    }
    
                    reader.endObject();
                    reader.close();
                } catch (Exception e) {
                    e.printStackTrace();
                    result.setResult(Util.API_001_RESULT_NG);
                }
            } catch (Exception e) {
                e.printStackTrace();
                result.setResult(Util.API_001_RESULT_NG);
            }
    

    readItemsArray function :

    // read items array
        private APIModel readItemsArray(JsonReader reader) throws IOException {
            APIModel result = new APIModel();
            String item_name, file_name, data;
            result.setResult(Util.API_001_RESULT_OK);
    
            reader.beginArray();
            while (reader.hasNext()) {
                item_name = "";
                file_name = "";
                data = "";
                reader.beginObject();
                while (reader.hasNext()) {
                    String name = reader.nextName();
                    if (name.equals("name")) {
                        item_name = reader.nextString();
                    } else if (name.equals("file")) {
                        file_name = reader.nextString();
                    } else if (name.equals("data")) {
                        data = reader.nextString();
                    } else {
                        reader.skipValue();
                    }
                }
                reader.endObject();
                result.populateModel("null", item_name, file_name, data);
            }
            reader.endArray();
            return result;
        }
    

    API Model Class :

    public class APIModel {
        private int result;
        private String error_title;
        private String error_message;
        private ArrayList type;
        private ArrayList item_name;
        private ArrayList file_name;
        private ArrayList data;
    
        public APIModel() {
            result = -1;
            error_title = "";
            error_message = "";
            setType(new ArrayList());
            setItem_name(new ArrayList());
            setFile_name(new ArrayList());
            setData(new ArrayList());
        }
    
        public void populateModel(String type, String item_name, String file_name, String data) {
            this.type.add(type);
            this.item_name.add(item_name);
            this.file_name.add(file_name);
            this.data.add(data);
        }
    
        public int getResult() {
            return result;
        }
    
        public void setResult(int result) {
            this.result = result;
        }
    
        public String getError_title() {
            return error_title;
        }
    
        public void setError_title(String error_title) {
            this.error_title = error_title;
        }
    
        public String getError_message() {
            return error_message;
        }
    
        public void setError_message(String error_message) {
            this.error_message = error_message;
        }
    
        public ArrayList getType() {
            return type;
        }
    
        public void setType(ArrayList type) {
            this.type = type;
        }
    
        public ArrayList getItem_name() {
            return item_name;
        }
    
        public void setItem_name(ArrayList item_name) {
            this.item_name = item_name;
        }
    
        public ArrayList getFile_name() {
            return file_name;
        }
    
        public void setFile_name(ArrayList file_name) {
            this.file_name = file_name;
        }
    
        public ArrayList getData() {
            return data;
        }
    
        public void setData(ArrayList data) {
            this.data = data;
        }
    
    
    }
    

    before I use the streaming API from google GSON I also got OOM error because the JSON data I got is very big data (many images and sounds in Base64 encoding) but with GSON streaming I can overcome that error because it reads the data per token not all at once. And for Jackson JSON library I think it also have streaming API and how to use it almost same with my implementation with google GSON. I hope my answer can help you and if you have another question about my answer feel free to ask in the comment :)

提交回复
热议问题