Хобрук: Ваш путь к мастерству в программировании

OutOfMemoryError при использовании Gson для анализа большого ответа JSON

URL url = new URL("http://pubapi.cryptsy.com/api.php?method=orderdatav2");
CryptsyCurrencyPairsReturn response = gson.fromJson(new InputStreamReader(url.openStream()), CryptsyCurrencyPairsReturn.class);

Это приводит к OutOfMemoryException для некоторых моих пользователей на старых устройствах Android. Как я могу разобрать этот большой ответ без нехватки памяти?


Ответы:


1

Парсинг больших данных за один раз всегда сложен и хлопотлив. Тем не менее, Gson поддерживает и это.

Вы должны искать com.google.gson.stream.JsonReader для выполнения разбора json с использованием потоков. Это позволит вам анализировать данные в порядке возрастания во время их загрузки и избавит устройства от ошибок OutOfMemory.

Для получения дополнительной информации прочитайте это.

24.09.2014

2

По моему опыту, вам нужно передавать данные JSON в потоковом режиме.
И да, вы можете использовать Google GSON для потоковой передачи данных JSON, это пример того, как это сделать:

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:

// 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:

public class APIModel {
    private int result;
    private String error_title;
    private String error_message;
    private ArrayList<String> type;
    private ArrayList<String> item_name;
    private ArrayList<String> file_name;
    private ArrayList<String> data;

    public APIModel() {
        result = -1;
        error_title = "";
        error_message = "";
        setType(new ArrayList<String>());
        setItem_name(new ArrayList<String>());
        setFile_name(new ArrayList<String>());
        setData(new ArrayList<String>());
    }

    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<String> getType() {
        return type;
    }

    public void setType(ArrayList<String> type) {
        this.type = type;
    }

    public ArrayList<String> getItem_name() {
        return item_name;
    }

    public void setItem_name(ArrayList<String> item_name) {
        this.item_name = item_name;
    }

    public ArrayList<String> getFile_name() {
        return file_name;
    }

    public void setFile_name(ArrayList<String> file_name) {
        this.file_name = file_name;
    }

    public ArrayList<String> getData() {
        return data;
    }

    public void setData(ArrayList<String> data) {
        this.data = data;
    }


}

прежде чем использовать потоковый API из google GSON, я также получил ошибку OOM, потому что данные JSON, которые я получил, представляют собой очень большие данные (много изображений и звуков в кодировке Base64), но с потоковой передачей GSON я могу преодолеть эту ошибку, потому что она считывает данные для каждого токена, а не все вместе. И для библиотеки Jackson JSON, я думаю, у нее также есть потоковый API и как его использовать почти так же, как и в моей реализации с google GSON. Я надеюсь, что мой ответ поможет вам, и если у вас есть еще вопросы по поводу моего ответа, не стесняйтесь спрашивать в комментарии :)

24.09.2014

3

Я рекомендую посмотреть JsonReader (API 11+) или другие параметры, рекомендованные здесь.

24.09.2014
Новые материалы

Создание кнопочного меню с использованием HTML, CSS и JavaScript
Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

Внедрите OAuth в свои веб-приложения для повышения безопасности
OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

Классы в JavaScript
class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

Как свинг-трейдеры могут использовать ИИ для больших выигрышей
По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

Как построить любой стол
Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

Обзор: Машинное обучение: классификация
Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

Разработка расширений Qlik Sense с qExt
Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..