2012-02-22 3 views
27

Java에서 gson 라이브러리 (http://code.google.com/p/google-gson/)를 사용하여 거대한 JSON 파일 (예 : http://eu.battle.net/auction-data/258993a3c6b974ef3e6f22ea6f822720/auctions.json)을 구문 분석하려고합니다.거대한 (초대형) JSON 파일을 구문 분석하기위한 최선의 방법

이 종류의 큰 파일 (약 80k 줄)을 구문 분석하는 데 가장 적합한 승인자가 무엇인지 알고 싶습니다. 그리고 처리하는 데 도움이되는 좋은 API를 알고 있다면 알려주세요. 라인별로

어떤 생각이 ...

  1. 읽기 라인과는 JSON 형식 제거 :하지만 그건 넌센스입니다.
  2. JSON 파일을이 파일을 다른 많은 파일로 분할하여 파일 크기를 줄이지 만 좋은 Java API를 찾지 못했습니다.
  3. 이 파일을 directlly nonSql 데이터베이스로 사용하고 파일을 보관하고 내 데이터베이스로 사용하십시오.

나는 정말로 조언/도움/메시지/:--)를 부탁드립니다. 감사합니다.

+0

Java EE 대안 : javax.json.stream.JsonParser – xonya

답변

27

Jackson으로 전환 할 필요가 없습니다. Gson 2.1은 혼합 트리 및 스트리밍 직렬화 및 비 직렬화를 허용하는 새로운 TypeAdapter 인터페이스를 도입했습니다.

API는 효율적이고 유연합니다. 트리와 바인딩 모드를 결합하는 예는 Gson's Streaming doc을 참조하십시오. 혼합 스트리밍 및 트리 모드보다 엄격하게 좋습니다. 구속력을 지니고 있으면 가치관의 중간 표현을 만드는 기억을 낭비하지 않아도됩니다.

Jackson과 마찬가지로 Gson에는 원치 않는 값을 반복적으로 건너 뛰는 API가 있습니다. Gson은 이것을 skipValue()이라고 부릅니다.

+0

나는 이것을 조사 할 것입니다! 공유 주셔서 감사합니다. – Dax

+0

'TypeAdapter'를 혼합 파싱으로 트리 구문 분석에 사용하는 좋은 예가 있습니까? 나는 매우 커지게되는 객체 목록에 그것을 혼합하고 싶습니다. 이 문서의 예제는'Message's 목록을 스트림 파싱하는 것이지만 당신이 어떻게 그 스트림 파서를 트리 파서에 묶을지는 보여주지 않습니다. (이것은 트리 파서를 스트림 파서에 연결하는 방법을 보여줍니다.) –

+0

예를 들면 : 객체 매핑을 정의하는'CustomType'과'CustomTypes extends ArrayList '이 있습니다. 각각의'CustomType'에 객체 매핑을 사용하는'TypeAdapter '을 만들었지 만, 전체 목록을 메모리에 저장하는 대신 (데이터베이스에 쓰는 대신) 빈리스트를 반환합니다. 그런 다음 포함하는 객체는 객체 매핑을 사용하여 간단히 구문 분석됩니다. –

25

Jackson Api 스트리밍 및 트리 모델 구문 분석 옵션을 결합하는 것이 매우 쉽습니다. 파일 전체를 스트리밍 방식으로 이동 한 다음 개별 개체를 트리로 읽을 수 있습니다 구조.

example으로의 다음 입력을 보자 :

{ 
    "records": [ 
    {"field1": "aaaaa", "bbbb": "ccccc"}, 
    {"field2": "aaa", "bbb": "ccc"} 
    ] , 
    "special message": "hello, world!" 
} 

그냥 필드가 드문 드문있는 또는 기록이 더 복잡한 구조를 갖는 상상한다.

다음 스 니펫은 스트림 및 트리 모델 구문 분석의 조합을 사용하여이 파일을 읽는 방법을 보여줍니다. 각 개별 레코드는 트리 구조로 읽지 만 파일 전체가 메모리로 읽히지 않으므로 최소한의 메모리를 사용하면서 기가 바이트 크기의 JSON 파일을 처리 할 수 ​​있습니다.

import org.codehaus.jackson.map.*; 
    import org.codehaus.jackson.*; 
    import java.io.File; 
    public class ParseJsonSample { 
     public static void main(String[] args) throws Exception { 
     JsonFactory f = new MappingJsonFactory(); 
     JsonParser jp = f.createJsonParser(new File(args[0])); 
     JsonToken current; 
     current = jp.nextToken(); 
     if (current != JsonToken.START_OBJECT) { 
      System.out.println("Error: root should be object: quiting."); 
      return; 
     } 
     while (jp.nextToken() != JsonToken.END_OBJECT) { 
      String fieldName = jp.getCurrentName(); 
      // move from field name to field value 
      current = jp.nextToken(); 
      if (fieldName.equals("records")) { 
      if (current == JsonToken.START_ARRAY) { 
       // For each of the records in the array 
       while (jp.nextToken() != JsonToken.END_ARRAY) { 
       // read the record into a tree model, 
       // this moves the parsing position to the end of it 
       JsonNode node = jp.readValueAsTree(); 
       // And now we have random access to everything in the object 
       System.out.println("field1: " + node.get("field1").getValueAsText()); 
       System.out.println("field2: " + node.get("field2").getValueAsText()); 
       } 
      } else { 
       System.out.println("Error: records should be an array: skipping."); 
       jp.skipChildren(); 
      } 
      } else { 
      System.out.println("Unprocessed property: " + fieldName); 
      jp.skipChildren(); 
      } 
     }     
     } 
    } 

당신이 추측 수 있듯이, nextToken()를 할 때마다 호출은 다음 구문 분석 이벤트를 제공합니다 : 개체, ..., 최종 개체, ..., 최종 배열을 시작, 배열을 시작, 필드 시작 개체를 시작 , ...

jp.readValueAsTree() 호출은 현재 구문 분석 위치 인 JSON 객체 또는 배열을 Jackson의 일반 JSON 트리 모델로 읽을 수있게 해줍니다. 이 작업을 수행하면 파일에 나타나는 순서 (예 : field1과 field2가 항상 같은 순서는 아님)에 관계없이 데이터에 임의로 액세스 할 수 있습니다. Jackson은 자신 만의 Java 객체에도 매핑을 지원합니다. jp.skipChildren()은 편리합니다. 포함 된 모든 이벤트에서 자신을 실행하지 않고도 전체 객체 트리 또는 배열을 건너 뛸 수 있습니다.

+0

코드가 정말 도움이되었습니다! 내 문제를 해결하고 마침내 내 힙 공간 예외를 없애 버릴 수 있습니다. 전에 한 파일을 읽었 기 때문에 :-) –

관련 문제