Jackson SAX parser throws exception when parsing huge JSON
我正在尝试用Jackson SAX解析器实现JSON数组迭代器(请不要问为什么)。
我的应用程序应该可以处理大文件(最多5 MiB),这是一个问题。
这就是我初始化JsonParser并调用迭代器创建的方式。
我创建InputStream并使用JSON初始化,并将其放在\ raw文件夹中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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; } |
这是我的迭代器类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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个字节的微小片段)。但是我接下来不能解析。
下一个数组具有带有简单对象的嵌套数组(如下所示):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | { "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。这不是对象或迭代器创建的问题:我可以删除解析器引发异常的地方,但是它将在同一位置失败。
这是堆栈跟踪:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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,但是它没有任何效果。
更新资料
有关某些行的信息
1 2 3 | 47: list.add(it.next()); 73: return parseNextObject(); 75: e.printStackTrace(); |
没什么特别的。
这是一个明显的问题:我忘记了在创建解析器后关闭流...