appendAllowed(true) breaks JSON array when the writer is opened/written/closed multiple times (original) (raw)
Bug description
When org.springframework.batch.infrastructure.item.json.JsonFileItemWriter is configured with setAppendAllowed(true) and used in multiple runs (open → write → close) against the same target file, the resulting file is not a valid JSON array. The second run appends data after the closing bracket (]) instead of inserting it inside the array with a comma.
Environment
Spring Batch 6.0.2
Steps to reproduce
Even with appendAllowed(true), after multiple runs the final file should remain a valid JSON array, and in the reproduction test below ["foo", "bar"] should be read correctly.
/*
- Copyright 2018-2022 the original author or authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License. */
package org.springframework.batch.infrastructure.item.json;
import java.io.File; import java.nio.file.Files;
import tools.jackson.databind.json.JsonMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.batch.infrastructure.item.Chunk; import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.batch.infrastructure.item.json.JsonFileItemWriter; import org.springframework.batch.infrastructure.item.json.JsonObjectMarshaller; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.WritableResource;
import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertThrows;
class JsonFileItemWriterTests {
private WritableResource resource;
@BeforeEach
void setUp() throws Exception {
File file = Files.createTempFile("test", "json").toFile();
this.resource = new FileSystemResource(file);
}
@Test
void appendAllowedShouldNotCorruptJsonArray() throws Exception {
JsonFileItemWriter<String> writer = new JsonFileItemWriter<>(this.resource, new JacksonJsonObjectMarshaller<>());
writer.setAppendAllowed(true);
writer.open(new ExecutionContext());
writer.write(Chunk.of("foo"));
writer.close();
writer.open(new ExecutionContext());
writer.write(Chunk.of("bar"));
writer.close();
String[] result = readJsonArrayOfStrings();
assertArrayEquals(new String[] { "foo", "bar" }, result);
}
private String[] readJsonArrayOfStrings() throws Exception {
File file = this.resource.getFile();
String raw = Files.readString(file.toPath());
System.out.println(raw);
return new JsonMapper().readValue(raw, String[].class);
}}
current json structure
Expected behavior
expect json structure