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

이로 인해 이전 Android 장치의 일부 사용자에 대해 OutOfMemoryException이 발생합니다. 메모리 부족없이이 큰 응답을 구문 분석하려면 어떻게해야합니까?Gson을 사용하여 큰 JSON 응답을 구문 분석 할 때 OutOfMemoryError

답변

4

한 번에 큰 데이터를 구문 분석하는 것은 항상 까다롭고 번거로운 작업입니다. 그러나 Gson에는이를 지원하는 멋진 기능이 함께 제공됩니다.

스트림을 사용하여 json 구문 분석을 수행하려면 com.google.gson.stream.JsonReader을 찾아야합니다. 이렇게하면 데이터를 다운로드하는 동안 증분 순서로 데이터를 구문 분석하고 OutOfMemory 오류로부터 장치를 절약 할 수 있습니다.

자세한 내용은 this을 참조하십시오.

+0

"내"upvote – juanmf

+1

@juanmf link fixed – waqaslam

1

JsonReader (API 11+) 또는 권장 옵션 here과 같은 다른 옵션을 살펴 보는 것이 좋습니다.

3

제 경험으로 볼 때 JSON 데이터를 스트리밍해야합니다.
그리고 네 당신이 그것을 수행하는 방법의 예입니다 JSON 데이터를 스트리밍 구글 GSON를 사용할 수 있습니다

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; 
    } 


} 

Google GSON에서 스트리밍 API를 사용하기 전에 JSON 데이터가 매우 큰 데이터 (많은 이미지와 Base64 인코딩의 소리)이기 때문에 OOM 오류가 발생했지만 GSON 스트리밍 토큰 당 데이터를 한꺼번에 읽지 않기 때문에 오류를 극복 할 수 있습니다. 그리고 잭슨 JSON 라이브러리의 경우 API 스트리밍과 Google GSON을 사용하여 구현할 때와 거의 동일한 방법을 사용하는 것으로 생각됩니다. 내 대답은 당신을 도울 수 있기를 바랍니다. 내 대답에 대한 다른 질문이 있으시면 자유롭게 의견을 물어보십시오 :)

관련 문제