Spring Batch: Как настроить FlatItemFileReader для чтения сжатого файла ND-JSON? - PullRequest
0 голосов
/ 23 июня 2019

Ввод

Новая строка JSON с разделителями, пример:

{"summersolstice":"21st June, 2019", //complex objects, arrays, etc ... }
{"summersolstice":"21st June, 2018", //complex objects, arrays, etc ... }
{"summersolstice":"21st June, 2017", //complex objects, arrays, etc ... }

Ограничение

Хотя я понимаю, что лучший способ - использовать новые блестящие устройства для чтения элементов JSONвыпущенная прошлым летом ( ссылка ), обновить пакетную версию до последней пока не представляется возможным.Это единственное ограничение.

Настоящий подход

На данный момент я следовал этому стековому ответу, но я не думаю, что T для FlatFileItemReader 1018 * - лучшая стратегия!На данный момент я просто принимаю его с помощью этого кода:

public class JsonItemReader extends FlatFileItemReader<Map<String, Object>> {

    public JsonItemReader(File file) {
        Resource resource = new BzipLazyResource(file); //on the fly unzipping
        setResource(resource);
        setLineMapper(new JsonLineMapper());
    }

    public JsonItemReader(String sourceFileName) {
        this(new File(sourceFileName));
    }
}

... и затем анализирую его просто в ItemProcessor, например:

public class JsonItemProcessor implements ItemProcessor<Map<String, Object>, List<Json>> {

    private ObjectMapper mapper = new ObjectMapper();
    private static final Logger logger = LoggerFactory.getLogger(JsonItemProcessor.class);

    public List<Json> process(Map<String, Object> jsonItem) throws Exception {
        JsonNode jsonNode = mapper.valueToTree(jsonItem);
        return parseJsonItems(jsonNode);
    }

Ресурсы:

1 Ответ

1 голос
/ 24 июня 2019

Нет необходимости в таком косвенном указании, расширяя FlatFileItemReader и создавая дополнительный процессор элементов для преобразования Map<String, Object> в List<Json> ..

Вот быстрый линейный картограф, который вы можете использовать с FlatFileItemReader:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.batch.item.file.LineMapper;

public class NDJsonLineMapper<T> implements LineMapper<T> {

    private Class<? extends T> targetType;

    private ObjectMapper objectMapper = new ObjectMapper(); // TODO could make this configurable

    public NDJsonLineMapper(Class<? extends T> targetType) {
        this.targetType = targetType;
    }

    @Override
    public T mapLine(String line, int lineNumber) throws Exception {
        return objectMapper.readValue(line, targetType);
    }
}

И его тест:

import org.junit.Assert;
import org.junit.jupiter.api.Test;

class NDJsonLineMapperTest {

    @Test
    void testNDJsonMapping() throws Exception {
        // given
        String jsonLine = "{\"id\":1,\"name\":\"foo\"}";
        NDJsonLineMapper<Person> lineMapper = new NDJsonLineMapper<>(Person.class);

        // when
        Person person = lineMapper.mapLine(jsonLine, 1);

        // then
        Assert.assertEquals(1, person.getId());
        Assert.assertEquals("foo", person.getName());

    }

    static class Person {

        private int id;
        private String name;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

}

Это пример варианта 1.2 в ссылке, которой вы поделились. Вы можете использовать его с FlatFileItemReader следующим образом:

@Bean
public FlatFileItemReader<Person> itemReader() {
    return new FlatFileItemReaderBuilder<Person>()
            .name("NDJsonItemReader")
            .resource(new FileSystemResource("file.ndjson"))
            .lineMapper(new NDJsonLineMapper<>(Person.class))
            .build();
}

Надеюсь, это поможет.

...