1

Jackson SAX パーサーを使用して JSON 配列反復子を実装しようとしています (理由は聞かないでください)。私のアプリは巨大なファイル (最大 5 MiB) で動作するはずですが、それが問題です。

これが、JsonParser を初期化し、イテレータの作成を呼び出す方法です。\raw フォルダに置かれた JSON で初期化された InputStream を作成します。

    プライベート JsonArrayIterator getIterator(String needle) が IOException をスローする
    {
        InputStream inputStream = getApplicationContext().getResources().openRawResource(R.raw.products);
        inputStream.mark(-1);

        試す {
        JsonParser jsonParser = createJsonParser(inputStream);

        // 関連のないコード

        新しい JsonArrayIterator(jsonParser) を返します。
    } キャッチ (IOException e) {
        e.printStackTrace();
    } 最後に {
        inputStream.close();
    }

        null を返します。
    }

そして、これが私のイテレータクラスです。

    private Object parseNextObject() は IOException をスローします {
        // 理由により ObjectMapper を使用していません
        HashMap nextObject = new HashMap();

        int オブジェクト数 = 1;

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

            if(currentToken == JsonToken.START_OBJECT) {
                ++objectsCount;
            }
            else if(currentToken == JsonToken.END_OBJECT) {
                --objectsCount;
            }
            それ以外の場合 (currentToken == JsonToken.START_ARRAY) {
                String currentName = currentParser.getCurrentName();
                ArrayList リスト = 新しい ArrayList(100);
                JsonArrayIterator it = new JsonArrayIterator(currentParser);

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

                nextObject.put(現在の名前、リスト);
            }
            そうしないと {
                // ここで例外がスローされます
                nextObject.put(currentParser.getCurrentName(), currentParser.getText());
            }
        }

        currentParser.nextToken(); // END_OBJECT をスキップ
        次のオブジェクトを返します。
    }

完璧に動作するようです...ああ、待ってください。

巨大なファイルに 3 つのセクション (名前付き配列) があります。最初に正常に解析されます (1000 バイト未満の小さなもの)。しかし、次は解析できません。

次の配列には、単純なオブジェクトを含むネストされた配列があります (このように):

    {
        "プロパティ":[
            {
                "id":"1",
                "タイトル":"\u0426\u0432\u0435\u0442",
                "値":[
                    {
                        "id":"1_2",
                        "タイトル":"\u0427\u0435\u0440\u043d\u044b\u0439"
                    }、
                    {
                        "id":"1_5005",
                        "タイトル":"\u0417\u0435\u043b\u0435\u043d\u044b\u0439"
                    }、
                    {
                        "id":"1_5006",
                        "タイトル":"\u0421\u0435\u0440\u044b\u0439"
                    }
                ]
            }
        ]
    }

値の 1 つのオブジェクトに対して、nextObject.put を呼び出します。currentParser.getCurrentName() は正常に実行され、正しい文字列が返されますが、currentParser.getText() は失敗します。これは JSON の問題ではありません。iOS では完全にマッピングされています。オブジェクトやイテレータの作成の問題ではありません。パーサーが例外をスローする場所を削除できますが、同じ場所で失敗します。

スタック トレースは次のとおりです。

    05-15 21:57:28.617: エラー/AndroidRuntime(14758): 致命的な例外: メイン
    java.lang.NullPointerException: 資産
    android.content.res.AssetManager.readAsset(ネイティブメソッド)で
    android.content.res.AssetManager.access$700(AssetManager.java:36)
    android.content.res.AssetManager$AssetInputStream.read(AssetManager.java:576) で
    com.fasterxml.jackson.core.json.UTF8StreamJsonParser.loadMore(UTF8StreamJsonParser.java:174)で
    com.fasterxml.jackson.core.base.ParserBase.loadMoreGuaranteed (ParserBase.java:425) で
    com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString2 (UTF8StreamJsonParser.java:1930) で
    com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString (UTF8StreamJsonParser.java:1911) で
    com.fasterxml.jackson.core.json.UTF8StreamJsonParser.getText (UTF8StreamJsonParser.java:276) で
    ru.studiomobile.JsonArrayIterator.parseNextObject (JsonArrayIterator.java:57) で
    ru.studiomobile.JsonArrayIterator.next(JsonArrayIterator.java:73) で
    ru.studiomobile.JsonArrayIterator.parseNextObject (JsonArrayIterator.java:47) で
    ru.studiomobile.JsonArrayIterator.next(JsonArrayIterator.java:73) で
    ru.studiomobile.MainActivity$2.onClick(MainActivity.java:81)で
    android.view.View.performClick(View.java:3127) で
    android.view.View$PerformClick.run(View.java:12025) で
    android.os.Handler.handleCallback(Handler.java:587) で
    android.os.Handler.dispatchMessage(Handler.java:92) で
    android.os.Looper.loop(Looper.java:132)で
    android.app.ActivityThread.main(ActivityThread.java:4126) で
    java.lang.reflect.Method.invokeNative(ネイティブ メソッド) で
    java.lang.reflect.Method.invoke(Method.java:491) で
    com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844) で
    com.android.internal.os.ZygoteInit.main (ZygoteInit.java:602) で
    dalvik.system.NativeStart.main (ネイティブ メソッド) で

Utf8StreamJsonParser というものがあることに気付きました。4000 に等しい _inputEnd という名前のフィールドがあります (なぜ 4000 なのですか?)。他のフィールド _inputPtr が大きくなると、例外がスローされます。どうすれば対処できますか?InputStream の代わりに定義済みのブロック サイズで BufferedInputStream を使用しようとしましたが、効果がありませんでした。

アップデート

いくつかの行についての情報

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

特にない。

4

1 に答える 1

3

明らかな問題でした: パーサーを作成した後にストリームを閉じるのを忘れていました...

于 2012-05-16T16:17:37.503 に答える