ObjectWriterTest.java
package tools.jackson.databind;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import tools.jackson.core.*;
import tools.jackson.core.io.SerializedString;
import tools.jackson.core.json.JsonWriteFeature;
import tools.jackson.databind.node.ObjectNode;
import static org.junit.jupiter.api.Assertions.*;
import static tools.jackson.databind.testutil.DatabindTestUtil.*;
/**
* Unit tests for checking features added to {@link ObjectWriter}, such
* as adding of explicit pretty printer.
*/
public class ObjectWriterTest
{
static class CloseableValue implements Closeable
{
public int x;
public boolean closed;
@Override
public void close() throws IOException {
closed = true;
}
}
private final ObjectMapper MAPPER = newJsonMapper();
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
static class PolyBase {
}
@JsonTypeName("A")
static class ImplA extends PolyBase {
public int value;
public ImplA(int v) { value = v; }
}
@JsonTypeName("B")
static class ImplB extends PolyBase {
public int b;
public ImplB(int v) { b = v; }
}
/*
/**********************************************************
/* Test methods, normal operation
/**********************************************************
*/
public void testPrettyPrinter() throws Exception
{
ObjectWriter writer = MAPPER.writer();
HashMap<String, Integer> data = new HashMap<String,Integer>();
data.put("a", 1);
// default: no indentation
assertEquals("{\"a\":1}", writer.writeValueAsString(data));
// and then with standard
writer = writer.withDefaultPrettyPrinter();
// pretty printer uses system-specific line feeds, so we do that as well.
String lf = System.getProperty("line.separator");
assertEquals("{" + lf + " \"a\" : 1" + lf + "}", writer.writeValueAsString(data));
// and finally, again without indentation
writer = writer.with((PrettyPrinter) null);
assertEquals("{\"a\":1}", writer.writeValueAsString(data));
}
public void testPrefetch() throws Exception
{
ObjectWriter writer = MAPPER.writer();
assertFalse(writer.hasPrefetchedSerializer());
writer = writer.forType(String.class);
assertTrue(writer.hasPrefetchedSerializer());
}
public void testObjectWriterFeatures() throws Exception
{
ObjectWriter writer = MAPPER.writer()
.without(JsonWriteFeature.QUOTE_PROPERTY_NAMES);
Map<String,Integer> map = new HashMap<String,Integer>();
map.put("a", 1);
assertEquals("{a:1}", writer.writeValueAsString(map));
// but can also reconfigure
assertEquals("{\"a\":1}", writer.with(JsonWriteFeature.QUOTE_PROPERTY_NAMES)
.writeValueAsString(map));
}
public void testObjectWriterWithNode() throws Exception
{
ObjectNode stuff = MAPPER.createObjectNode();
stuff.put("a", 5);
ObjectWriter writer = MAPPER.writerFor(JsonNode.class);
String json = writer.writeValueAsString(stuff);
assertEquals("{\"a\":5}", json);
}
public void testPolymorphicWithTyping() throws Exception
{
ObjectWriter writer = MAPPER.writerFor(PolyBase.class);
String json;
json = writer.writeValueAsString(new ImplA(3));
assertEquals(a2q("{'type':'A','value':3}"), json);
json = writer.writeValueAsString(new ImplB(-5));
assertEquals(a2q("{'type':'B','b':-5}"), json);
}
public void testNoPrefetch() throws Exception
{
ObjectWriter w = MAPPER.writer()
.without(SerializationFeature.EAGER_SERIALIZER_FETCH);
ByteArrayOutputStream out = new ByteArrayOutputStream();
w.writeValue(out, Integer.valueOf(3));
out.close();
assertEquals("3", out.toString("UTF-8"));
}
public void testWithCloseCloseable() throws Exception
{
ObjectWriter w = MAPPER.writer()
.with(SerializationFeature.CLOSE_CLOSEABLE);
assertTrue(w.isEnabled(SerializationFeature.CLOSE_CLOSEABLE));
CloseableValue input = new CloseableValue();
assertFalse(input.closed);
byte[] json = w.writeValueAsBytes(input);
assertNotNull(json);
assertTrue(input.closed);
input.close();
// and via explicitly passed generator
JsonGenerator g = MAPPER.createGenerator(new StringWriter());
input = new CloseableValue();
assertFalse(input.closed);
w.writeValue(g, input);
assertTrue(input.closed);
g.close();
input.close();
}
public void testViewSettings() throws Exception
{
ObjectWriter w = MAPPER.writer();
ObjectWriter newW = w.withView(String.class);
assertNotSame(w, newW);
assertSame(newW, newW.withView(String.class));
// Avoid using the default Locale so that a new ObjectWriter will be
// created when calling `with(Locale)`.
Locale newLocale = notTheDefaultLocale();
newW = w.with(newLocale);
assertNotSame(w, newW);
assertSame(newW, newW.with(newLocale));
}
private Locale notTheDefaultLocale() {
return Arrays.stream(Locale.getAvailableLocales())
.filter(locale -> !locale.equals(Locale.getDefault()))
.findAny()
.get();
}
public void testMiscSettings() throws Exception
{
ObjectWriter w = MAPPER.writer();
assertSame(MAPPER.tokenStreamFactory(), w.generatorFactory());
assertFalse(w.hasPrefetchedSerializer());
assertNotNull(w.typeFactory());
ObjectWriter newW = w.with(Base64Variants.MODIFIED_FOR_URL);
assertNotSame(w, newW);
assertSame(newW, newW.with(Base64Variants.MODIFIED_FOR_URL));
w = w.withAttributes(Collections.emptyMap());
w = w.withAttribute("a", "b");
assertEquals("b", w.getAttributes().getAttribute("a"));
w = w.withoutAttribute("a");
assertNull(w.getAttributes().getAttribute("a"));
FormatSchema schema = new BogusSchema();
try {
newW = w.with(schema);
fail("Should not pass");
} catch (IllegalArgumentException e) {
verifyException(e, "Cannot use FormatSchema");
}
}
public void testRootValueSettings() throws Exception
{
ObjectWriter w = MAPPER.writer();
// First, root name:
ObjectWriter newW = w.withRootName("foo");
assertNotSame(w, newW);
assertSame(newW, newW.withRootName(PropertyName.construct("foo")));
w = newW;
newW = w.withRootName((String) null);
assertNotSame(w, newW);
assertSame(newW, newW.withRootName((PropertyName) null));
// Then root value separator
w = w.withRootValueSeparator(new SerializedString(","));
assertSame(w, w.withRootValueSeparator(new SerializedString(",")));
assertSame(w, w.withRootValueSeparator(","));
newW = w.withRootValueSeparator("/");
assertNotSame(w, newW);
assertSame(newW, newW.withRootValueSeparator("/"));
newW = w.withRootValueSeparator((String) null);
assertNotSame(w, newW);
newW = w.withRootValueSeparator((SerializableString) null);
assertNotSame(w, newW);
}
public void testFeatureSettings() throws Exception
{
ObjectWriter w = MAPPER.writer();
assertFalse(w.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));
assertFalse(w.isEnabled(StreamWriteFeature.STRICT_DUPLICATE_DETECTION));
ObjectWriter newW = w.with(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS,
SerializationFeature.INDENT_OUTPUT);
assertNotSame(w, newW);
assertTrue(newW.isEnabled(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS));
assertTrue(newW.isEnabled(SerializationFeature.INDENT_OUTPUT));
assertSame(newW, newW.with(SerializationFeature.INDENT_OUTPUT));
assertSame(newW, newW.withFeatures(SerializationFeature.INDENT_OUTPUT));
newW = w.withFeatures(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS,
SerializationFeature.INDENT_OUTPUT);
assertNotSame(w, newW);
newW = w.without(SerializationFeature.FAIL_ON_EMPTY_BEANS,
SerializationFeature.EAGER_SERIALIZER_FETCH);
assertNotSame(w, newW);
assertFalse(newW.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS));
assertFalse(newW.isEnabled(SerializationFeature.EAGER_SERIALIZER_FETCH));
assertSame(newW, newW.without(SerializationFeature.FAIL_ON_EMPTY_BEANS));
assertSame(newW, newW.withoutFeatures(SerializationFeature.FAIL_ON_EMPTY_BEANS));
assertNotSame(w, w.withoutFeatures(SerializationFeature.FAIL_ON_EMPTY_BEANS,
SerializationFeature.EAGER_SERIALIZER_FETCH));
}
public void testStreamWriteFeatures() throws Exception
{
ObjectWriter w = MAPPER.writer();
assertNotSame(w, w.with(JsonWriteFeature.ESCAPE_NON_ASCII));
assertNotSame(w, w.withFeatures(JsonWriteFeature.ESCAPE_NON_ASCII));
assertTrue(w.isEnabled(StreamWriteFeature.AUTO_CLOSE_TARGET));
assertNotSame(w, w.without(StreamWriteFeature.AUTO_CLOSE_TARGET));
assertNotSame(w, w.withoutFeatures(StreamWriteFeature.AUTO_CLOSE_TARGET));
}
/*
/**********************************************************
/* Test methods, failures
/**********************************************************
*/
public void testArgumentChecking() throws Exception
{
final ObjectWriter w = MAPPER.writer();
try {
w.acceptJsonFormatVisitor((JavaType) null, null);
fail("Should not pass");
} catch (IllegalArgumentException e) {
verifyException(e, "argument \"type\" is null");
}
}
public void testSchema() throws Exception
{
try {
MAPPER.writerFor(String.class)
.with(new BogusSchema())
.writeValueAsBytes("foo");
fail("Should not pass");
} catch (IllegalArgumentException e) {
verifyException(e, "Cannot use FormatSchema");
}
}
public void test_createGenerator_OutputStream() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = MAPPER.writer().createGenerator(outputStream);
jsonGenerator.writeString("value");
jsonGenerator.close();
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "\"value\"");
// the stream has not been closed by close
outputStream.write(1);
}
public void test_createGenerator_File() throws Exception
{
Path path = Files.createTempFile("", "");
JsonGenerator jsonGenerator = MAPPER.writer().createGenerator(path.toFile(), JsonEncoding.UTF8);
jsonGenerator.writeString("value");
jsonGenerator.close();
assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "\"value\"");
}
public void test_createGenerator_Path() throws Exception
{
Path path = Files.createTempFile("", "");
JsonGenerator jsonGenerator = MAPPER.writer().createGenerator(path, JsonEncoding.UTF8);
jsonGenerator.writeString("value");
jsonGenerator.close();
assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "\"value\"");
}
public void test_createGenerator_Writer() throws Exception
{
Writer writer = new StringWriter();
JsonGenerator jsonGenerator = MAPPER.writer().createGenerator(writer);
jsonGenerator.writeString("value");
jsonGenerator.close();
assertEquals(writer.toString(), "\"value\"");
// the writer has not been closed by close
writer.append('1');
}
public void test_createGenerator_DataOutput() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
DataOutput dataOutput = new DataOutputStream(outputStream);
JsonGenerator jsonGenerator = MAPPER.writer().createGenerator(dataOutput);
jsonGenerator.writeString("value");
jsonGenerator.close();
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "\"value\"");
// the data output has not been closed by close
dataOutput.write(1);
}
public void test_createGenerator_failsIfArgumentIsNull() throws Exception
{
ObjectWriter objectWriter = MAPPER.writer();
test_method_failsIfArgumentIsNull(() -> objectWriter.createGenerator((OutputStream) null));
test_method_failsIfArgumentIsNull(() -> objectWriter.createGenerator((OutputStream) null, null));
test_method_failsIfArgumentIsNull(() -> objectWriter.createGenerator((DataOutput) null));
test_method_failsIfArgumentIsNull(() -> objectWriter.createGenerator((Path) null, null));
test_method_failsIfArgumentIsNull(() -> objectWriter.createGenerator((File) null, null));
test_method_failsIfArgumentIsNull(() -> objectWriter.createGenerator((Writer) null));
}
public void test_writeValue_OutputStream() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
MAPPER.writer().writeValue(outputStream, "value");
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "\"value\"");
// the stream has not been closed by close
outputStream.write(1);
}
public void test_writeValue_File() throws Exception
{
Path path = Files.createTempFile("", "");
MAPPER.writer().writeValue(path.toFile(), "value");
assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "\"value\"");
}
public void test_writeValue_Path() throws Exception
{
Path path = Files.createTempFile("", "");
MAPPER.writer().writeValue(path, "value");
assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "\"value\"");
}
public void test_writeValue_Writer() throws Exception
{
Writer writer = new StringWriter();
MAPPER.writer().writeValue(writer, "value");
assertEquals(writer.toString(), "\"value\"");
// the writer has not been closed by close
writer.append('1');
}
public void test_writeValue_DataOutput() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
DataOutput dataOutput = new DataOutputStream(outputStream);
MAPPER.writer().writeValue(dataOutput, "value");
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "\"value\"");
// the data output has not been closed by close
dataOutput.write(1);
}
public void test_writeValue_JsonGenerator() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = MAPPER.createGenerator(outputStream);
MAPPER.writer().writeValue(jsonGenerator, "value");
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "\"value\"");
// the output stream has not been closed by close
outputStream.write(1);
}
public void test_writeValue_failsIfArgumentIsNull() throws Exception
{
ObjectMapper objectMapper = MAPPER;
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValue((OutputStream) null, null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValue((DataOutput) null, null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValue((Path) null, null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValue((File) null, null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValue((Writer) null, null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValue((JsonGenerator) null, null));
}
public void test_writeValues_OutputStream() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
SequenceWriter sequenceWriter = MAPPER.writer().writeValues(outputStream);
sequenceWriter.write("value");
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "\"value\"");
// the stream has not been closed by close
outputStream.write(1);
}
public void test_writeValues_File() throws Exception
{
Path path = Files.createTempFile("", "");
SequenceWriter sequenceWriter = MAPPER.writer().writeValues(path.toFile());
sequenceWriter.write("value");
assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "\"value\"");
}
public void test_writeValues_Path() throws Exception
{
Path path = Files.createTempFile("", "");
SequenceWriter sequenceWriter = MAPPER.writer().writeValues(path);
sequenceWriter.write("value");
assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "\"value\"");
}
public void test_writeValues_Writer() throws Exception
{
Writer writer = new StringWriter();
SequenceWriter sequenceWriter = MAPPER.writer().writeValues(writer);
sequenceWriter.write("value");
assertEquals(writer.toString(), "\"value\"");
// the writer has not been closed by close
writer.append('1');
}
public void test_writeValues_DataOutput() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
DataOutput dataOutput = new DataOutputStream(outputStream);
SequenceWriter sequenceWriter = MAPPER.writer().writeValues(dataOutput);
sequenceWriter.write("value");
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "\"value\"");
// the data output has not been closed by close
dataOutput.write(1);
}
public void test_writeValues_JsonGenerator() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = MAPPER.createGenerator(outputStream);
SequenceWriter sequenceWriter = MAPPER.writer().writeValues(jsonGenerator);
sequenceWriter.write("value");
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "\"value\"");
// the data output has not been closed by close
outputStream.write(1);
}
public void test_writeValues_failsIfArgumentIsNull() throws Exception
{
ObjectMapper objectMapper = MAPPER;
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValues((OutputStream) null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValues((DataOutput) null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValues((Path) null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValues((File) null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValues((Writer) null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValues((JsonGenerator) null));
}
public void test_writeValuesAsArray_OutputStream() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
SequenceWriter sequenceWriter = MAPPER.writer().writeValuesAsArray(outputStream);
sequenceWriter.write("value");
sequenceWriter.flush();
sequenceWriter.close();
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "[\"value\"]");
// the stream has not been closed by close
outputStream.write(1);
}
public void test_writeValuesAsArray_File() throws Exception
{
Path path = Files.createTempFile("", "");
SequenceWriter sequenceWriter = MAPPER.writer().writeValuesAsArray(path.toFile());
sequenceWriter.write("value");
sequenceWriter.flush();
sequenceWriter.close();
assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "[\"value\"]");
}
public void test_writeValuesAsArray_Path() throws Exception
{
Path path = Files.createTempFile("", "");
SequenceWriter sequenceWriter = MAPPER.writer().writeValuesAsArray(path);
sequenceWriter.write("value");
sequenceWriter.flush();
sequenceWriter.close();
assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "[\"value\"]");
}
public void test_writeValuesAsArray_Writer() throws Exception
{
Writer writer = new StringWriter();
SequenceWriter sequenceWriter = MAPPER.writer().writeValuesAsArray(writer);
sequenceWriter.write("value");
sequenceWriter.flush();
sequenceWriter.close();
assertEquals(writer.toString(), "[\"value\"]");
// the writer has not been closed by close
writer.append('1');
}
public void test_writeValuesAsArray_DataOutput() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
DataOutput dataOutput = new DataOutputStream(outputStream);
SequenceWriter sequenceWriter = MAPPER.writer().writeValuesAsArray(dataOutput);
sequenceWriter.write("value");
sequenceWriter.flush();
sequenceWriter.close();
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "[\"value\"]");
// the data output has not been closed by close
dataOutput.write(1);
}
public void test_writeValuesAsArray_JsonGenerator() throws Exception
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = MAPPER.createGenerator(outputStream);
SequenceWriter sequenceWriter = MAPPER.writer().writeValuesAsArray(jsonGenerator);
sequenceWriter.write("value");
sequenceWriter.flush();
sequenceWriter.close();
jsonGenerator.flush();
jsonGenerator.close();
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "[\"value\"]");
// the data output has not been closed by close
outputStream.write(1);
}
public void test_writeValuesAsArray_failsIfArgumentIsNull() throws Exception
{
ObjectMapper objectMapper = MAPPER;
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValuesAsArray((OutputStream) null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValuesAsArray((DataOutput) null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValuesAsArray((Path) null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValuesAsArray((File) null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValuesAsArray((Writer) null));
test_method_failsIfArgumentIsNull(() -> objectMapper.writer().writeValuesAsArray((JsonGenerator) null));
}
private static void test_method_failsIfArgumentIsNull(Runnable runnable) throws Exception
{
try {
runnable.run();
fail("IllegalArgumentException expected.");
} catch (IllegalArgumentException expected) {
verifyException(expected, "Argument \"");
verifyException(expected, "\" is null");
}
}
}