首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >春批Json自定义ItemWriter

春批Json自定义ItemWriter
EN

Stack Overflow用户
提问于 2016-05-25 16:36:09
回答 2查看 5.9K关注 0票数 0

我想从数据库中写入json格式的文件。我有一个ItemWriter实现的原型,非常简单。

代码语言:javascript
复制
import java.util.ArrayList;
import java.util.List;

import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.item.ItemWriter;
import org.springframework.core.io.Resource;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class CustomItemWriter<T> implements ItemWriter<T>, StepExecutionListener {
    private Gson gson;
    private Resource resource;
    private boolean shouldDeleteIfExists = true;
    private List<T> allItems = new ArrayList<T>();

    @Override
    public void write(List<? extends T> items) throws Exception {
        System.out.println("this is the begin " + items.size());
        allItems.addAll(items);
    }

    public Resource getResource() {
        return resource;
    }

    public void setResource(Resource resource) {
        this.resource = resource;
    }

    public boolean isShouldDeleteIfExists() {
        return shouldDeleteIfExists;
    }

    public void setShouldDeleteIfExists(boolean shouldDeleteIfExists) {
        this.shouldDeleteIfExists = shouldDeleteIfExists;
    }

    @Override
    public ExitStatus afterStep(StepExecution arg0) {
        //write ALL to the output file
        System.out.println(gson.toJson(allItems)); 
        return null;
    }

    @Override
    public void beforeStep(StepExecution arg0) {
        gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").disableHtmlEscaping().create();
    }
}

这里解决的问题是,write方法将每个commitInterval发送给输出文件一个JSON数组,我只是希望文件中有一个惟一的JSON数组。

步骤运行后实现StepExecutionListener;我可以将整个数组发送到输出文件,并将其转换为JSON,并将其写入输出文件(很好!)。

我的问题是,是这样做的正确方法吗?,我认为写到每个commitInterval文件的好处,但我不确定我的解决方案。这是可行的,但我不想解决这个问题,去证明另一个问题。

EN

回答 2

Stack Overflow用户

发布于 2016-05-25 16:59:45

实际上,您希望用每个块来刷新对文件的写入,否则就会失去重新启动的能力。

假设您对每行一个JSON对象都满意,我可能只会使用一个FlatFileItemWriter和一个自定义LineAggregator来将每个对象转换成一个JSON字符串。类似于这样的东西:

代码语言:javascript
复制
public class JsonLineAggregator<T> implements LineAggregator<T>, StepExecutionListener {

    private Gson gson = new Gson();
    private boolean isFirstObject = true;

    @Override
    public String aggregate(final T item) {
        if (isFirstObject) {
            isFirstObject = false;
            return "[" + gson.toJson(item);
        }
        return "," + gson.toJson(item);
    }

    public void setGson(final Gson gson) {
        this.gson = gson;
    }

    @Override
    public void beforeStep(final StepExecution stepExecution) {
        if (stepExecution.getExecutionContext().containsKey("isFirstObject")) {
            isFirstObject = Boolean.parseBoolean(stepExecution.getExecutionContext().getString("isFirstObject"));
        }
    }

    @Override
    public ExitStatus afterStep(final StepExecution stepExecution) {
        stepExecution.getExecutionContext().putString("isFirstObject", Boolean.toString(isFirstObject));
        return null;
    }
}

编辑:更新了上面的LineAggregator实现,以演示如何使其输出类似于JSON列表的内容。

请注意,您还希望将一个FlatFileFooterCallback注册到添加最终"]“的FlatFileItemWriter中。

代码语言:javascript
复制
public class JsonFlatFileFooterCallback implements FlatFileFooterCallback {

    @Override
    public void writeFooter(final Writer writer) throws IOException {
        writer.write("]");
    }
}
票数 2
EN

Stack Overflow用户

发布于 2017-09-26 12:02:49

谢谢你的解决方案。

在Xml中,可以这样添加。

代码语言:javascript
复制
    <property name="resource" value="file:opt/output.json" />  <!--  #{jobParameters['input.file.name']} -->
    <property name="shouldDeleteIfExists" value="true" />

    <property name="lineAggregator">
        <bean
            class="com.package.JsonLineAggregator">
        </bean>
    </property>

</bean> 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37443046

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档