Парсер Jackson SAX выдает исключение при разборе огромного JSON

1

Я пытаюсь реализовать итератор массива JSON с парсером Jackson SAX (пожалуйста, не спрашивайте, почему). Мое приложение должно работать с огромными файлами (до 5 MiB), и это проблема.

То, как я инициализирую JsonParser и вызываю создание итератора. Я создаю InputStream, инициализированный JSON, помещенным в папку \raw.

    private JsonArrayIterator getIterator(String needle) throws IOException
    {
        InputStream inputStream = getApplicationContext().getResources().openRawResource(R.raw.products);
        inputStream.mark(-1);

        try {
        JsonParser jsonParser = createJsonParser(inputStream);

        // Some unrelated code

        return new JsonArrayIterator(jsonParser);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        inputStream.close();
    }

        return null;
    }

И вот мой класс итератора.


    private Object parseNextObject() throws IOException {
        // I'm not using ObjectMapper because of reasons
        HashMap nextObject = new HashMap();

        int objectsCount = 1;

        while (objectsCount > 0) {
            JsonToken currentToken = currentParser.nextValue();

            if(currentToken == JsonToken.START_OBJECT) {
                ++objectsCount;
            }
            else if(currentToken == JsonToken.END_OBJECT) {
                --objectsCount;
            }
            else if(currentToken == JsonToken.START_ARRAY) {
                String currentName = currentParser.getCurrentName();
                ArrayList list = new ArrayList(100);
                JsonArrayIterator it = new JsonArrayIterator(currentParser);

                while (it.hasNext()) {
                    list.add(it.next());
                }

                nextObject.put(currentName, list);
            }
            else {
                // Here exception is throwed
                nextObject.put(currentParser.getCurrentName(), currentParser.getText());
            }
        }

        currentParser.nextToken();  // Skip END_OBJECT
        return nextObject;
    }

Кажется, он работает... О, ЖДИТЕ.

У меня есть 3 раздела (называемые массивами) в каком-то огромном файле. Он успешно разбирает сначала (крошечный, менее 1000 байт). Но я не могу разобрать дальше.

Следующий массив имеет вложенный массив с простыми объектами (например, это):


    {
        "properties":[
            {
                "id":"1",
                "title":"\u0426\u0432\u0435\u0442",
                "values":[
                    {
                        "id":"1_2",
                        "title":"\u0427\u0435\u0440\u043d\u044b\u0439"
                    },
                    {
                        "id":"1_5005",
                        "title":"\u0417\u0435\u043b\u0435\u043d\u044b\u0439"
                    },
                    {
                        "id":"1_5006",
                        "title":"\u0421\u0435\u0440\u044b\u0439"
                    }
                ]
            }
        ]
    }

Для одного объекта в значениях я вызываю nextObject.put. currentParser.getCurrentName() запускается успешно и возвращает правильную строку, но currentParser.getText() терпит неудачу. Это не проблема JSON: она отлично отображается на iOS. Это не проблема создания объекта или итератора: я могу удалить это, когда синтаксический анализатор генерирует исключение, но он не будет работать в одном месте.

Вот трассировка стека:


    05-15 21:57:28.617: ERROR/AndroidRuntime(14758): FATAL EXCEPTION: main
    java.lang.NullPointerException: asset
    at android.content.res.AssetManager.readAsset(Native Method)
    at android.content.res.AssetManager.access$700(AssetManager.java:36)
    at android.content.res.AssetManager$AssetInputStream.read(AssetManager.java:576)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.loadMore(UTF8StreamJsonParser.java:174)
    at com.fasterxml.jackson.core.base.ParserBase.loadMoreGuaranteed(ParserBase.java:425)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString2(UTF8StreamJsonParser.java:1930)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString(UTF8StreamJsonParser.java:1911)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.getText(UTF8StreamJsonParser.java:276)
    at ru.studiomobile.JsonArrayIterator.parseNextObject(JsonArrayIterator.java:57)
    at ru.studiomobile.JsonArrayIterator.next(JsonArrayIterator.java:73)
    at ru.studiomobile.JsonArrayIterator.parseNextObject(JsonArrayIterator.java:47)
    at ru.studiomobile.JsonArrayIterator.next(JsonArrayIterator.java:73)
    at ru.studiomobile.MainActivity$2.onClick(MainActivity.java:81)
    at android.view.View.performClick(View.java:3127)
    at android.view.View$PerformClick.run(View.java:12025)
    at android.os.Handler.handleCallback(Handler.java:587)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:132)
    at android.app.ActivityThread.main(ActivityThread.java:4126)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
    at dalvik.system.NativeStart.main(Native Method)

Я заметил, что есть что-то, что называется Utf8StreamJsonParser. Он имеет поле с именем _inputEnd равным 4000 (почему 4000?). Когда другое поле, _inputPtr, становится больше, оно генерирует исключение. Как я могу справиться с этим? Я попытался использовать BufferedInputStream с предопределенным размером блока вместо InputStream, но это не повлияло.

Обновить

Информация о некоторых строках


    47: list.add(it.next());  
    73: return parseNextObject();  
    75: e.printStackTrace();

Ничего особенного.

  • 0
    Прежде всего, почему вы используете Jackson SAX SCNR. Пожалуйста, добавьте некоторую информацию, связанную со строками, о строках 47, 73 и 75 файла JsonArrayIterator.java.
  • 0
    @rekire Мне нужен парсер JSON SAX, поэтому я использую Джексона. Если я преобразую мои JSON-файлы в DOM, они будут поглощать всю кучу. Я добавил информацию об этих строках в пост.
Показать ещё 2 комментария
Теги:
jackson

1 ответ

3
Лучший ответ

Это была очевидная проблема: я забыл, что закрываю поток после создания парсера...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню