Melhor abordagem para analisar um arquivo JSON enorme (extra grande)

Estou tentando analisar um arquivo JSON enorme (como http://eu.battle.net/auction-data/258993a3c6b974ef3e6f22ea6f822720/auctions.json ) usando a biblioteca gson ( http://code.google.com/p/google- gson / ) em JAVA.

Eu gostaria de saber qual é a melhor abordagem para analisar esse tipo de arquivo grande (cerca de 80k linhas) e se você conhece uma boa API que pode me ajudar a processar isso.

Alguma idéia…

  1. leia linha por linha e livre-se do formato JSON: mas isso não faz sentido.
  2. reduza o arquivo JSON dividindo esse arquivo em muitos outros: mas não encontrei nenhuma API Java boa para isso.
  3. use este arquivo diretamente como database nonSql, mantenha o arquivo e use-o como meu database.

Eu realmente aprecio adices / help / messages / 🙂 Obrigado.

Você não precisa mudar para Jackson. O Gson 2.1 introduziu uma nova interface TypeAdapter que permite a serialização e desserialização de tree mista e streaming.

A API é eficiente e flexível. Veja o documento de streaming do Gson para um exemplo de combinação de tree e modos de binding . Isso é estritamente melhor do que os modos de streaming e tree mistos; com a vinculação, você não perde a memory criando uma representação intermediária de seus valores.

Como Jackson, Gson tem APIs para pular recursivamente um valor indesejado; Gson chama esse skipValue () .

Vou sugerir dar uma olhada no Jackson Api . É muito fácil combinar as opções de análise de stream e de modelo de tree: você pode percorrer o arquivo como um todo de uma maneira de stream e depois ler objects individuais em uma estrutura de tree.

Como exemplo , vamos pegar a seguinte input:

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

Imagine os campos sendo esparsos ou os registros tendo uma estrutura mais complexa.

O snippet a seguir ilustra como esse arquivo pode ser lido usando uma combinação de análise de stream e de modelo de tree. Cada registro individual é lido em uma estrutura em tree, mas o arquivo nunca é lido em sua totalidade na memory, tornando possível processar gigabytes de arquivos JSON em tamanho enquanto usa memory mínima.

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

Como você pode imaginar, a chamada nextToken () toda vez dá o próximo evento de análise: object inicial, campo inicial, matriz inicial, object inicial, …, object final, …, matriz final, …

A chamada jp.readValueAsTree() permite ler o que está na posição de análise atual, um object JSON ou matriz, no modelo de tree JSON genérico de Jackson. Depois de ter isso, você pode acessar os dados aleatoriamente, independentemente da ordem em que as coisas aparecem no arquivo (no exemplo field1 e field2 nem sempre estão na mesma ordem). Jackson suporta o mapeamento em seus próprios objects Java também. O jp.skipChildren () é conveniente: ele permite pular uma tree de objects completa ou uma matriz sem ter que passar por todos os events contidos nela.