与杰克逊解组“Json输入流必须以一系列Json对象开头”

问题描述 投票:0回答:2

解组仅包含单个JSON对象的文件时出现错误:“IllegalStateException:Json输入流必须以Json对象数组开头”我找不到任何解决方法而且我不明白它为什么要这样做是这样。

@Bean
public ItemReader<JsonHar> reader(@Value("file:${json.resources.path}/*.json") Resource[] resources) {
    log.info("Processing JSON resources: {}", Arrays.toString(resources));
    JsonItemReader<JsonHar> delegate = new JsonItemReaderBuilder<JsonHar>()
            .jsonObjectReader(new JacksonJsonObjectReader<>(JsonHar.class))
            .resource(resources[0])  //FIXME had to force this, but fails anyway because the file is "{...}" and not "[...]"
            .name("jsonItemReader")
            .build();
    MultiResourceItemReader<JsonHar> reader = new MultiResourceItemReader<>();
    reader.setDelegate(delegate);
    reader.setResources(resources);
    return reader;
}

我需要一种解组单个目标文件的方法,强制数组的重点是什么(在我的用例中我没有)?

json jackson spring-batch unmarshalling
2个回答
0
投票

我不明白为什么必须如此。

JsonItemReader旨在读取an array of objects,因为批处理通常是关于处理包含大量项目的数据源,而不是单个项目。

我找不到任何解决方法

JsonObjectReader正是您所寻找的:您可以实现它来读取单个json对象并将其与JsonItemReader一起使用(在构造时或使用setter)。这不是一种解决方法,而是针对像您这样的特定用例设计的策略界面。


0
投票

认为这可能不太理想,这就是我如何处理这种情况:

@Bean
public ItemReader<JsonHar> reader(@Value("file:${json.resources.path}/*.json") Resource[] resources) {
    log.info("Processing JSON resources: {}", Arrays.toString(resources));
    JsonItemReader<JsonHar> delegate = new JsonItemReaderBuilder<JsonHar>()
            .jsonObjectReader(new JacksonJsonObjectReader<>(JsonHar.class))
            .resource(resources[0]) //DEBUG had to force this because of NPE...
            .name("jsonItemReader")
            .build();
    MultiResourceItemReader<JsonHar> reader = new MultiResourceItemReader<>();
    reader.setDelegate(delegate);
    reader.setResources(Arrays.stream(resources)
            .map(WrappedResource::new) // forcing the bride to look good enough
            .toArray(Resource[]::new));
    return reader;
}
@RequiredArgsConstructor
static class WrappedResource implements Resource {
    @Delegate(excludes = InputStreamSource.class)
    private final Resource resource;
    @Override
    public InputStream getInputStream() throws IOException {
        log.info("Wrapping resource: {}", resource.getFilename());
        InputStream in = resource.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in, UTF_8));
        String wrap = reader.lines().collect(Collectors.joining())
                .replaceAll("[^\\x00-\\xFF]", "");  // strips off all non-ASCII characters
        return new ByteArrayInputStream(("[" + wrap + "]").getBytes(UTF_8));
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.