2012-02-22 4 views
27

Я пытаюсь разобрать некоторый огромный файл JSON (например, http://eu.battle.net/auction-data/258993a3c6b974ef3e6f22ea6f822720/auctions.json) с использованием библиотеки gson (http://code.google.com/p/google-gson/) в JAVA.JAVA - Лучший подход для синтаксического анализа огромного (особо большого) файла JSON

Я хотел бы знать, что лучше всего разбирать этот вид большого файла (около 80 тыс. Строк), и если вы можете знать хороший API, который может помочь мне обработать это.

Некоторые идеи ...

  1. читать построчно и избавиться от формата JSON: но это ерунда.
  2. уменьшить файл JSON, разделив этот файл на многие другие: но для этого я не нашел хорошего Java API.
  3. используйте этот файл directlly как базу данных nonSql, сохраните файл и используйте его в качестве моей базы данных.

Я бы по достоинству оценил adices/help/messages/:-) Спасибо.

+0

Альтернатива Java EE: javax.json.stream.JsonParser – xonya

ответ

27

Вам не нужно переключаться на Джексон. Gson 2.1 представила новый интерфейс TypeAdapter, который позволяет проводить сериализацию и десериализацию серого дерева и потоковой передачи.

API эффективный и гибкий. См. Gson's Streaming doc для примера объединения дерева и привязки . Это строго лучше, чем смешанные потоковые и древовидные режимы; с привязкой вы не теряете память, создавая промежуточное представление ваших значений.

Как и Джексон, у Gson есть API, чтобы рекурсивно пропускать нежелательное значение; Gson называет это skipValue().

+0

Я проверю это! Спасибо за обмен – Dax

+0

Есть ли хороший пример использования 'TypeAdapter' для смешанного анализа потока в дереве? У меня есть случай, когда я хочу смешать его в списке объектов, который становится очень большим. Примером в документации является поток, анализирующий список «Message's», но он не показывает, как вы привязываете этот анализатор потока к парному парсеру. (Он показывает, как вы привязываете дерево-парсер в парсере потока) –

+0

Например: у меня есть 'CustomType' для определения сопоставления объектов, а' CustomTypes extends ArrayList '. Я делаю «TypeAdapter », который использует сопоставление объектов для каждого «CustomType», но просто возвращает пустой список в конце, чтобы избежать хранения всего списка в памяти (вместо этого записывайте их в базу данных). И тогда содержащий объект анализируется просто с использованием сопоставления объектов. –

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, в дженерическую модель JSON Jackson. После этого вы можете получить доступ к данным случайным образом, независимо от порядка, в котором вещи появляются в файле (в поле примера1 и поле2 не всегда находятся в одном порядке). Джексон также поддерживает отображение на ваши собственные объекты Java. Jp.skipChildren() удобен: он позволяет пропустить полное дерево объектов или массив без необходимости запускаться над всеми событиями, содержащимися в нем.

+0

Ваш код был действительно полезным! Я приспособил его к моей проблеме и смог, наконец, избавиться от своих исключений в кучном пространстве, потому что я прочитал файл за один раз раньше :-) –

 Смежные вопросы

  • Нет связанных вопросов^_^