Джексон - Работа с массивами объектов, добавление и удаление

Я работаю с API Джексона на Java для работы с JSON. Я работал с ним немного здесь и там, но ничего слишком глубокого.

В настоящее время я ищу хороший способ взять массив объектов JSON (либо через поток, либо через строку), созданный из списка POJO, и добавить или удалить POJO. В случае добавления проверка дубликатов на самом деле не нужна. В качестве простого примера предположим, что у меня есть этот массив, построенный из списка объектов Java с одной переменной с именем «поле»:

[{"field":"value"},{"field":"value2"}]

И я хотел бы добавить объект того же типа с «полем», установленным на «value3». Я мог бы просто десериализовать весь массив в список объектов Java, добавить новый объект, а затем сериализовать его обратно в JSON, но это кажется излишним. Было бы лучше, если бы я мог использовать Джексона, чтобы просто сериализовать новый объект и добавить его в конец массива JSON. То же самое относится к удалению существующего объекта из массива.


person user1017413    schedule 10.10.2014    source источник
comment
Немного спорный вопрос. Используете ли вы jackson для добавления его в качестве объекта или просто редактируете строку? Лично я бы придерживался Джексона, а не комбинировал их. это быстро   -  person TedTrippin    schedule 10.10.2014
comment
Я не пытаюсь напрямую манипулировать строкой. Я копался в документации по Джексону, но мне еще предстоит пройти через многое, и мне еще предстоит узнать, как выполнить эту операцию непосредственно с Джексоном. В идеале я мог бы обернуть InputStream с помощью Jackson и записать его непосредственно в OutputStream, либо добавив новый объект в конце, либо удалив существующий объект по мере прохождения JSON между потоками.   -  person user1017413    schedule 10.10.2014


Ответы (1)


Я нашел способ, но, как ни странно, он более чем в два раза медленнее, чем прямой метод deserialize-add-reserialze со списком из 500 POJO, каждый из которых имеет три поля, и становится только хуже с большим количеством объектов.

ObjectMapper mapper = new ObjectMapper();
JsonParser parser = mapper.getJsonFactory().createJsonParser(input);
JsonGenerator gen = mapper.getJsonFactory().createJsonGenerator(output, JsonEncoding.UTF8);
gen.writeStartArray();
parser.nextToken();
while (parser.nextToken() == JsonToken.START_OBJECT) {
    //gen.writeTree(parser.readValueAsTree());
    //parser.skipChildren();
    //EDIT: This is much faster as the only method in the loop:
    gen.copyCurrentStructure(parser);
}
gen.writeTree(mapper.valueToTree(/*new Object to add*/);
gen.writeEndArray();
gen.close();
parser.close();

Даже если я не получаю каждый объект в виде дерева, а вместо этого итеративно перемещаю их как поля/значения, это немного быстрее, но все же значительно медленнее, чем альтернатива. Этого следует ожидать или есть лучший способ обрабатывать его как потоковые данные, а не массовый метод JSON-to-Java-to-JSON?

РЕДАКТИРОВАТЬ: АГА! Обнаружено, что JsonGenerator может напрямую копировать текущую структуру из JsonParser withcopyCurrentStructure(JsonParser). Использование этого в цикле while работает быстрее и значительно опережает метод грубой силы.

person user1017413    schedule 10.10.2014
comment
Да, есть некоторые скрытые накладные расходы при выполнении преобразований значений (в/из дерева или POJO); поэтому прямое копирование из JsonParser в JsonGeneraror более эффективно. Вот почему либо ваша первоначальная идея (прочитать в List, добавить, записать), либо перейти на низкоуровневый Streaming API — лучший подход. - person StaxMan; 11.10.2014