【问题标题】:Unmarshalling with Jackson "The Json input stream must start with an array of Json objects"使用 Jackson 解组“Json 输入流必须以 Json 对象数组开头”
【发布时间】:2019-09-11 11:20:13
【问题描述】:

解组仅包含单个 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;
}

我需要一种方法来解组单个对象文件,强制数组有什么意义(我的用例中没有)??

【问题讨论】:

  • 注:显然,JacksonJsonObjectReader 和 GsonJsonObjectReader 的工作方式相同

标签: json jackson spring-batch unmarshalling


【解决方案1】:

我不明白为什么会这样。

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

我找不到任何解决方法

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

【讨论】:

  • 谢谢。但是我不能将对象阅读器用作 MultiResourceItemReader 的委托,可以吗?它没有实现 ResourceAwareItemReaderItemStream
  • 不,MultiResourceItemReader 的代表仍应为JsonItemReader。您只需要使用带有JsonItemReader 的自定义JsonObjectReader 而不是JacksonJsonObjectReader。从视觉上看,这将是:MultiResourceItemReader -- 委托给 --> JsonItemReader -- 使用 --> 您的自定义 JsonObjectReader。希望这会有所帮助。
  • 好的,知道了!对不起,很慢。由于 JsonItemReader javadoc 说阅读结构是一个列表,我认为对象(非复数)阅读器只是处理单个值
【解决方案2】:

虽然这可能不太理想,但我是这样处理这种情况的:

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

【讨论】:

    【解决方案3】:

    绝对不理想@thomas-escolan。正如@mahmoud-ben-hassine 指出的那样,理想的做法是编写一个自定义阅读器。

    如果一些新的 SOF 用户偶然发现了这个问题,我在这里留下一个code example on how to do it

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-14
      • 1970-01-01
      • 2012-11-08
      相关资源
      最近更新 更多