Spring Batch:如何配置FlatItemFileReader以读取压缩的ND-JSON文件?

时间:2019-06-23 04:22:55

标签: java json spring jackson spring-batch

输入

以新行分隔的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 ... }

约束

虽然我了解最好的方法是使用去年夏天(link)发布的崭新的JSON项目阅读器开发人员,但将批处理版本更新为最新版本尚不可行。那是唯一的约束。

当前方法

到目前为止,我一直遵循this堆栈答案,但是我不认为为T使用FlatFileItemReader是最好的策略! 到目前为止,我只是将其与以下代码一起使用:

Map<String, Object>

...然后在ItemProcessor中对其进行简单解析,例如:

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

资源:

1 个答案:

答案 0 :(得分:1)

通过扩展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();
}

希望这会有所帮助。