什么是Java中巨大的Json字符串unescape的最佳方法

时间:2019-05-23 19:05:00

标签: java android json

我有一个适用于Android应用程序的项目,该项目可以下载庞大的Json String并提取程序所需的有用信息。但是该文件确实很大(将近100mb)才能存储到内存中,所以我需要读取它的较小部分。

我所看到的Json字符串和所有字符串都是一行。因此,由于OOM(内存不足),我无法逐行读取

{"Tag":"[{\"mySubTag\":\"myValue\/myValue\"},{\"mySubTag\":\"myValueWithAnotherEscapedStringInside\\xyz\/likeThis\"},...]"}

通常,我使用来自JsonObject的标签作为字符串提取它们,然后从“ Tag”属性获取字符串值,然后再次使用此字符串创建新的JsonArray,以便从JsonArray类自动取消转义,但Android不允许放置Json文件(或String)进入内存。我试图通过流删除反斜杠,但如果subTag值内部包含转义字符,则它不是正确的unescape方法。

我的问题是什么是完成这项工作的最佳方式和性能友好的方式?

(注意:对不起,英语不好)

更新1:

在@pskink重新命令后,我使用了android.util.JsonReader,并且编写了如下代码:

JsonReader jsonReader = new JsonReader(new FileReader(f));//f is defined previous code but not shown!
jsonReader.beginObject();                   
String name = jsonReader.nextName();        
String value = jsonReader.nextString();         
Log.d(AppConstants.TAG, "name: " + name);   
Log.d(AppConstants.TAG, "value: " + value.length());//value is so big I only care about its length
JsonReader jsonReader1 = new JsonReader(new StringReader(value));
while (jsonReader1.hasNext()) {
    JsonToken token = jsonReader1.peek();
    switch (token) {
        case BEGIN_ARRAY:
            jsonReader1.beginArray();
            Log.d(AppConstants.TAG, "BEGIN_ARRAY");
            continue;
        case END_ARRAY:
            jsonReader1.endArray();
            Log.d(AppConstants.TAG, "END_ARRAY");
            continue;
        case BEGIN_OBJECT:
            jsonReader1.beginObject();
            Log.d(AppConstants.TAG, "BEGIN_OBJECT");
            continue;
        case END_OBJECT:
            jsonReader1.endObject();
            Log.d(AppConstants.TAG, "END_OBJECT");
            continue;
        case NAME:
            Log.d(AppConstants.TAG, "name: " + jsonReader1.nextName());
            continue;
        case STRING:
            Log.d(AppConstants.TAG, "String: " + jsonReader1.nextString());
            continue;
        case NUMBER:
            Log.d(AppConstants.TAG, "number: " + jsonReader1.nextString());
            continue;
        case BOOLEAN:
            Log.d(AppConstants.TAG, "boolean: " + jsonReader1.nextBoolean());
            continue;
        case NULL:
            jsonReader1.nextNull();
            continue;
        case END_DOCUMENT:
            Log.d(AppConstants.TAG, "END_DOCUMENT");
            break;

    }
}

我的输出是:

Tag
69387276
BEGIN_ARRAY
BEGIN_OBJECT
name: mySubTag
String: myValue/myValue

我很困惑为什么其余数组元素被忽略了!

更新2:

经过一些调试过程,我意识到 hasNext()方法返回“如果 current 数组或对象具有另一个元素,则返回true”。但是当前不是后来的元素,所以我像这样更新了while循环:

while (jsonReader1.peek()!=JsonToken.END_DOCUMENT) {
    JsonToken token = jsonReader1.peek();
    switch(token){
    ...
    }
}

1 个答案:

答案 0 :(得分:1)

@pskink建议android.util.JsonReader使用此库编写代码后解决了我的问题。要查看我的代码,请查看有问题的更新。

感谢@pskink。