diff --git a/src/main/java/com/fasterxml/jackson/core/JsonFactory.java b/src/main/java/com/fasterxml/jackson/core/JsonFactory.java index 1427ba5021..a754660b25 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonFactory.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonFactory.java @@ -19,8 +19,8 @@ import com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer; import com.fasterxml.jackson.core.util.BufferRecycler; import com.fasterxml.jackson.core.util.BufferRecyclers; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.core.util.JacksonFeature; +import com.fasterxml.jackson.core.util.Separators; /** * The main factory class of Jackson package, used to configure and @@ -197,7 +197,7 @@ public static int collectDefaults() { */ protected final static int DEFAULT_GENERATOR_FEATURE_FLAGS = JsonGenerator.Feature.collectDefaults(); - public final static SerializableString DEFAULT_ROOT_VALUE_SEPARATOR = DefaultPrettyPrinter.DEFAULT_ROOT_VALUE_SEPARATOR; + public final static SerializableString DEFAULT_ROOT_VALUE_SEPARATOR = new SerializedString(Separators.DEFAULT_ROOT_VALUE_SEPARATOR); /** * @since 2.10 diff --git a/src/main/java/com/fasterxml/jackson/core/json/JsonGeneratorImpl.java b/src/main/java/com/fasterxml/jackson/core/json/JsonGeneratorImpl.java index 6aef2e857e..807a92fda8 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/JsonGeneratorImpl.java +++ b/src/main/java/com/fasterxml/jackson/core/json/JsonGeneratorImpl.java @@ -7,7 +7,6 @@ import com.fasterxml.jackson.core.io.CharTypes; import com.fasterxml.jackson.core.io.CharacterEscapes; import com.fasterxml.jackson.core.io.IOContext; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.core.util.JacksonFeatureSet; import com.fasterxml.jackson.core.util.VersionUtil; @@ -92,7 +91,7 @@ public abstract class JsonGeneratorImpl extends GeneratorBase * @since 2.1 */ protected SerializableString _rootValueSeparator - = DefaultPrettyPrinter.DEFAULT_ROOT_VALUE_SEPARATOR; + = JsonFactory.DEFAULT_ROOT_VALUE_SEPARATOR; /** * Flag that is set if quoting is not to be added around diff --git a/src/main/java/com/fasterxml/jackson/core/util/DefaultPrettyPrinter.java b/src/main/java/com/fasterxml/jackson/core/util/DefaultPrettyPrinter.java index 98f650a4a1..779a2de98f 100644 --- a/src/main/java/com/fasterxml/jackson/core/util/DefaultPrettyPrinter.java +++ b/src/main/java/com/fasterxml/jackson/core/util/DefaultPrettyPrinter.java @@ -33,7 +33,9 @@ public class DefaultPrettyPrinter * root values: a single space character. * * @since 2.1 + * @deprecated in 2.16. Use the Separators API instead. */ + @Deprecated public final static SerializedString DEFAULT_ROOT_VALUE_SEPARATOR = new SerializedString(" "); /** @@ -70,8 +72,10 @@ public interface Indenter /** * String printed between root-level values, if any. + * + * @deprecated in 2.16. Use Separators API instead. */ - protected final SerializableString _rootSeparator; + protected SerializableString _rootSeparator; // // // Config, other white space configuration @@ -79,7 +83,10 @@ public interface Indenter * By default we will add spaces around colons used to * separate object fields and values. * If disabled, will not use spaces around colon. + * + * @deprecated in 2.16. Use Separators API instead. */ + @Deprecated protected boolean _spacesInObjectEntries = true; // // // State: @@ -99,7 +106,17 @@ public interface Indenter * @since 2.9 */ protected String _objectFieldValueSeparatorWithSpaces; + + /** + * @since 2.16 + */ + protected String _objectEntrySeparator; + /** + * @since 2.16 + */ + protected String _arrayValueSeparator; + /* /********************************************************** /* Life-cycle (construct, configure) @@ -107,7 +124,7 @@ public interface Indenter */ public DefaultPrettyPrinter() { - this(DEFAULT_ROOT_VALUE_SEPARATOR); + this(DEFAULT_SEPARATORS); } /** @@ -118,7 +135,9 @@ public DefaultPrettyPrinter() { * calls {@link #DefaultPrettyPrinter(SerializableString)} * * @param rootSeparator String to use as root value separator + * @deprecated in 2.16. Use the Separators API instead. */ + @Deprecated public DefaultPrettyPrinter(String rootSeparator) { this((rootSeparator == null) ? null : new SerializedString(rootSeparator)); } @@ -128,16 +147,17 @@ public DefaultPrettyPrinter(String rootSeparator) { * if null, no separator is printed. * * @param rootSeparator String to use as root value separator + * @deprecated in 2.16. Use the Separators API instead. */ + @Deprecated public DefaultPrettyPrinter(SerializableString rootSeparator) { - _rootSeparator = rootSeparator; - withSeparators(DEFAULT_SEPARATORS); - } - - public DefaultPrettyPrinter(DefaultPrettyPrinter base) { - this(base, base._rootSeparator); + this(DEFAULT_SEPARATORS.withRootSeparator(rootSeparator.getValue())); } + /** + * @deprecated in 2.16. Use the Separators API instead. + */ + @Deprecated public DefaultPrettyPrinter(DefaultPrettyPrinter base, SerializableString rootSeparator) { @@ -148,17 +168,58 @@ public DefaultPrettyPrinter(DefaultPrettyPrinter base, _separators = base._separators; _objectFieldValueSeparatorWithSpaces = base._objectFieldValueSeparatorWithSpaces; + _objectEntrySeparator = base._objectEntrySeparator; + _arrayValueSeparator = base._arrayValueSeparator; _rootSeparator = rootSeparator; } + /** + * @since 2.16 + */ + public DefaultPrettyPrinter(Separators separators) + { + _separators = separators; + + _rootSeparator = separators.getRootSeparator() == null ? null : new SerializedString(separators.getRootSeparator()); + _objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSpacing().apply( + separators.getObjectFieldValueSeparator()); + _objectEntrySeparator = separators.getObjectEntrySpacing().apply(separators.getObjectEntrySeparator()); + _arrayValueSeparator = separators.getArrayValueSpacing().apply(separators.getArrayValueSeparator()); + } + + /** + * Copy constructor + * + * @since 2.16 + */ + public DefaultPrettyPrinter(DefaultPrettyPrinter base) { + _rootSeparator = base._rootSeparator; + + _arrayIndenter = base._arrayIndenter; + _objectIndenter = base._objectIndenter; + _spacesInObjectEntries = base._spacesInObjectEntries; + _nesting = base._nesting; + + _separators = base._separators; + _objectFieldValueSeparatorWithSpaces = base._objectFieldValueSeparatorWithSpaces; + _objectEntrySeparator = base._objectEntrySeparator; + _arrayValueSeparator = base._arrayValueSeparator; + } + + /** + * @deprecated in 2.16. Use the Separators API instead. + */ + @Deprecated public DefaultPrettyPrinter withRootSeparator(SerializableString rootSeparator) { if (_rootSeparator == rootSeparator || (rootSeparator != null && rootSeparator.equals(_rootSeparator))) { return this; } - return new DefaultPrettyPrinter(this, rootSeparator); + Separators separators = _separators.withRootSeparator(rootSeparator == null ? null : rootSeparator.getValue()); + return new DefaultPrettyPrinter(this) + .withSeparators(separators); } /** @@ -167,7 +228,9 @@ public DefaultPrettyPrinter withRootSeparator(SerializableString rootSeparator) * @return This pretty-printer instance (for call chaining) * * @since 2.6 + * @deprecated in 2.16. Use the Separators API instead. */ + @Deprecated public DefaultPrettyPrinter withRootSeparator(String rootSeparator) { return withRootSeparator((rootSeparator == null) ? null : new SerializedString(rootSeparator)); } @@ -180,7 +243,7 @@ public void indentObjectsWith(Indenter i) { _objectIndenter = (i == null) ? NopIndenter.instance : i; } - // @since 2.3 + /** @since 2.3 */ public DefaultPrettyPrinter withArrayIndenter(Indenter i) { if (i == null) { i = NopIndenter.instance; @@ -193,7 +256,7 @@ public DefaultPrettyPrinter withArrayIndenter(Indenter i) { return pp; } - // @since 2.3 + /** @since 2.3 */ public DefaultPrettyPrinter withObjectIndenter(Indenter i) { if (i == null) { i = NopIndenter.instance; @@ -215,7 +278,9 @@ public DefaultPrettyPrinter withObjectIndenter(Indenter i) { * @return This pretty-printer instance (for call chaining) * * @since 2.3 + * @deprecated in 2.16. Use the Separators API instead. */ + @Deprecated public DefaultPrettyPrinter withSpacesInObjectEntries() { return _withSpaces(true); } @@ -229,7 +294,9 @@ public DefaultPrettyPrinter withSpacesInObjectEntries() { * @return This pretty-printer instance (for call chaining) * * @since 2.3 + * @deprecated in 2.16. Use the Separators API instead. */ + @Deprecated public DefaultPrettyPrinter withoutSpacesInObjectEntries() { return _withSpaces(false); } @@ -239,7 +306,9 @@ protected DefaultPrettyPrinter _withSpaces(boolean state) if (_spacesInObjectEntries == state) { return this; } - DefaultPrettyPrinter pp = new DefaultPrettyPrinter(this); + + Separators copy = _separators.withObjectFieldValueSpacing(state ? Separators.Spacing.BOTH : Separators.Spacing.NONE); + DefaultPrettyPrinter pp = withSeparators(copy); pp._spacesInObjectEntries = state; return pp; } @@ -254,9 +323,16 @@ protected DefaultPrettyPrinter _withSpaces(boolean state) * @since 2.9 */ public DefaultPrettyPrinter withSeparators(Separators separators) { - _separators = separators; - _objectFieldValueSeparatorWithSpaces = " " + separators.getObjectFieldValueSeparator() + " "; - return this; + DefaultPrettyPrinter result = new DefaultPrettyPrinter(this); + result._separators = separators; + + result._rootSeparator = separators.getRootSeparator() == null ? null : new SerializedString(separators.getRootSeparator()); + result._objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSpacing().apply( + separators.getObjectFieldValueSeparator()); + result._objectEntrySeparator = separators.getObjectEntrySpacing().apply(separators.getObjectEntrySeparator()); + result._arrayValueSeparator = separators.getArrayValueSpacing().apply(separators.getArrayValueSeparator()); + + return result; } /* @@ -315,11 +391,7 @@ public void beforeObjectEntries(JsonGenerator g) throws IOException @Override public void writeObjectFieldValueSeparator(JsonGenerator g) throws IOException { - if (_spacesInObjectEntries) { - g.writeRaw(_objectFieldValueSeparatorWithSpaces); - } else { - g.writeRaw(_separators.getObjectFieldValueSeparator()); - } + g.writeRaw(_objectFieldValueSeparatorWithSpaces); } /** @@ -334,7 +406,7 @@ public void writeObjectFieldValueSeparator(JsonGenerator g) throws IOException @Override public void writeObjectEntrySeparator(JsonGenerator g) throws IOException { - g.writeRaw(_separators.getObjectEntrySeparator()); + g.writeRaw(_objectEntrySeparator); _objectIndenter.writeIndentation(g, _nesting); } @@ -378,7 +450,7 @@ public void beforeArrayValues(JsonGenerator g) throws IOException { @Override public void writeArrayValueSeparator(JsonGenerator g) throws IOException { - g.writeRaw(_separators.getArrayValueSeparator()); + g.writeRaw(_arrayValueSeparator); _arrayIndenter.writeIndentation(g, _nesting); } diff --git a/src/main/java/com/fasterxml/jackson/core/util/MinimalPrettyPrinter.java b/src/main/java/com/fasterxml/jackson/core/util/MinimalPrettyPrinter.java index 72b9c99f3a..868cc68f72 100644 --- a/src/main/java/com/fasterxml/jackson/core/util/MinimalPrettyPrinter.java +++ b/src/main/java/com/fasterxml/jackson/core/util/MinimalPrettyPrinter.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.PrettyPrinter; +import com.fasterxml.jackson.core.util.Separators.Spacing; /** * {@link PrettyPrinter} implementation that adds no indentation, @@ -46,7 +47,7 @@ public MinimalPrettyPrinter() { public MinimalPrettyPrinter(String rootValueSeparator) { _rootValueSeparator = rootValueSeparator; - _separators = DEFAULT_SEPARATORS; + _separators = DEFAULT_SEPARATORS.withObjectFieldValueSpacing(Spacing.NONE); } public void setRootValueSeparator(String sep) { diff --git a/src/main/java/com/fasterxml/jackson/core/util/Separators.java b/src/main/java/com/fasterxml/jackson/core/util/Separators.java index 9d63ab3d8b..5837d7825a 100644 --- a/src/main/java/com/fasterxml/jackson/core/util/Separators.java +++ b/src/main/java/com/fasterxml/jackson/core/util/Separators.java @@ -15,9 +15,53 @@ public class Separators implements Serializable { private static final long serialVersionUID = 1; + /** + * Constant that specifies default "root-level" separator to use between + * root values: a single space character. + * + * @since 2.16 + */ + public final static String DEFAULT_ROOT_VALUE_SEPARATOR = " "; + + /** + * Define the spacing around elements like commas and colons. + * + * @since 2.16 + */ + public enum Spacing { + NONE("", ""), + BEFORE(" ", ""), + AFTER("", " "), + BOTH(" ", " "); + + private final String spacesBefore; + private final String spacesAfter; + + private Spacing(String spacesBefore, String spacesAfter) { + this.spacesBefore = spacesBefore; + this.spacesAfter = spacesAfter; + } + + public String spacesBefore() { + return spacesBefore; + } + + public String spacesAfter() { + return spacesAfter; + } + + public String apply(char separator) { + return spacesBefore + separator + spacesAfter; + } + } + private final char objectFieldValueSeparator; + private final Spacing objectFieldValueSpacing; private final char objectEntrySeparator; + private final Spacing objectEntrySpacing; private final char arrayValueSeparator; + private final Spacing arrayValueSpacing; + private final String rootSeparator; public static Separators createDefaultInstance() { return new Separators(); @@ -27,37 +71,111 @@ public Separators() { this(':', ',', ','); } - public Separators(char objectFieldValueSeparator, - char objectEntrySeparator, char arrayValueSeparator) { + /** + * Create an instance with the specified separator characters. There will be spaces before and + * after the objectFieldValueSeparator and none around the other two. + */ + public Separators( + char objectFieldValueSeparator, + char objectEntrySeparator, + char arrayValueSeparator + ) { + this(DEFAULT_ROOT_VALUE_SEPARATOR, + objectFieldValueSeparator, Spacing.BOTH, + objectEntrySeparator, Spacing.NONE, + arrayValueSeparator, Spacing.NONE); + } + + /** + * Create an instance with the specified separator characters and spaces around those characters. + * + * @since 2.16 + */ + public Separators( + String rootSeperator, + char objectFieldValueSeparator, + Spacing objectFieldValueSpacing, + char objectEntrySeparator, + Spacing objectEntrySpacing, + char arrayValueSeparator, + Spacing arrayValueSpacing + ) { + this.rootSeparator = rootSeperator; this.objectFieldValueSeparator = objectFieldValueSeparator; + this.objectFieldValueSpacing = objectFieldValueSpacing; this.objectEntrySeparator = objectEntrySeparator; + this.objectEntrySpacing = objectEntrySpacing; this.arrayValueSeparator = arrayValueSeparator; + this.arrayValueSpacing = arrayValueSpacing; } + public Separators withRootSeparator(String sep) { + return (rootSeparator.equals(sep)) ? this + : new Separators(sep, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, arrayValueSeparator, arrayValueSpacing); + } + public Separators withObjectFieldValueSeparator(char sep) { return (objectFieldValueSeparator == sep) ? this - : new Separators(sep, objectEntrySeparator, arrayValueSeparator); + : new Separators(rootSeparator, sep, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, arrayValueSeparator, arrayValueSpacing); } + /** @since 2.16 */ + public Separators withObjectFieldValueSpacing(Spacing spacing) { + return (objectFieldValueSpacing == spacing) ? this + : new Separators(rootSeparator, objectFieldValueSeparator, spacing, objectEntrySeparator, objectEntrySpacing, arrayValueSeparator, arrayValueSpacing); + } + public Separators withObjectEntrySeparator(char sep) { return (objectEntrySeparator == sep) ? this - : new Separators(objectFieldValueSeparator, sep, arrayValueSeparator); + : new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, sep, objectEntrySpacing, arrayValueSeparator, arrayValueSpacing); + } + + /** @since 2.16 */ + public Separators withObjectEntrySpacing(Spacing spacing) { + return (objectEntrySpacing == spacing) ? this + : new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, spacing, arrayValueSeparator, arrayValueSpacing); } public Separators withArrayValueSeparator(char sep) { return (arrayValueSeparator == sep) ? this - : new Separators(objectFieldValueSeparator, objectEntrySeparator, sep); + : new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, sep, arrayValueSpacing); + } + + /** @since 2.16 */ + public Separators withArrayValueSpacing(Spacing spacing) { + return (arrayValueSpacing == spacing) ? this + : new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, arrayValueSeparator, spacing); + } + + /** @since 2.16 */ + public String getRootSeparator() { + return rootSeparator; } public char getObjectFieldValueSeparator() { return objectFieldValueSeparator; } + /** @since 2.16 */ + public Spacing getObjectFieldValueSpacing() { + return objectFieldValueSpacing; + } + public char getObjectEntrySeparator() { return objectEntrySeparator; } + /** @since 2.16 */ + public Spacing getObjectEntrySpacing() { + return objectEntrySpacing; + } + public char getArrayValueSeparator() { return arrayValueSeparator; } + + /** @since 2.16 */ + public Spacing getArrayValueSpacing() { + return arrayValueSpacing; + } } diff --git a/src/test/java/com/fasterxml/jackson/core/util/TestDefaultPrettyPrinter.java b/src/test/java/com/fasterxml/jackson/core/util/TestDefaultPrettyPrinter.java index a65c011aeb..123a0bfca9 100644 --- a/src/test/java/com/fasterxml/jackson/core/util/TestDefaultPrettyPrinter.java +++ b/src/test/java/com/fasterxml/jackson/core/util/TestDefaultPrettyPrinter.java @@ -4,7 +4,10 @@ import java.io.IOException; import java.io.StringWriter; +import org.assertj.core.api.ThrowingConsumer; + import com.fasterxml.jackson.core.*; +import com.fasterxml.jackson.core.util.Separators.Spacing; public class TestDefaultPrettyPrinter extends BaseTest { @@ -81,61 +84,173 @@ public void testTabIndent() throws IOException assertEquals(EXP, _printTestData(pp, false)); assertEquals(EXP, _printTestData(pp, true)); } + + public void testObjectFieldValueSpacingAfter() throws IOException + { + Separators separators = new Separators() + .withObjectFieldValueSpacing(Spacing.AFTER); + PrettyPrinter pp = new DefaultPrettyPrinter() + .withObjectIndenter(new DefaultIndenter(" ", "\n")) + .withSeparators(separators); + String EXP = "{\n" + + " \"name\": \"John Doe\",\n" + + " \"age\": 3.14\n" + + "}"; + assertEquals(EXP, _printTestData(pp, false)); + assertEquals(EXP, _printTestData(pp, true)); + } + + public void testObjectFieldValueSpacingNone() throws IOException + { + Separators separators = new Separators() + .withObjectFieldValueSpacing(Spacing.NONE); + PrettyPrinter pp = new DefaultPrettyPrinter() + .withObjectIndenter(new DefaultIndenter(" ", "\n")) + .withSeparators(separators); + String EXP = "{\n" + + " \"name\":\"John Doe\",\n" + + " \"age\":3.14\n" + + "}"; + assertEquals(EXP, _printTestData(pp, false)); + assertEquals(EXP, _printTestData(pp, true)); + } + + public void testCopyConfigOld() throws IOException + { + Separators separators = new Separators() + .withObjectFieldValueSpacing(Spacing.AFTER) + .withObjectEntrySpacing(Spacing.AFTER) + .withArrayValueSpacing(Spacing.AFTER); + DefaultPrettyPrinter pp = new DefaultPrettyPrinter() + .withObjectIndenter(new DefaultIndenter(" ", "\n")) + .withSeparators(separators); + String expected = _printTestData(pp, false); + assertEquals(expected, _printTestData(pp, true)); + + @SuppressWarnings("deprecation") // Testing the old API + DefaultPrettyPrinter copy = pp.withRootSeparator(DefaultPrettyPrinter.DEFAULT_ROOT_VALUE_SEPARATOR); + assertEquals(expected, _printTestData(copy, false)); + assertEquals(expected, _printTestData(copy, true)); + } + + public void testCopyConfigNew() throws IOException + { + Separators separators = new Separators() + .withObjectFieldValueSpacing(Spacing.AFTER) + .withObjectEntrySpacing(Spacing.AFTER) + .withArrayValueSpacing(Spacing.AFTER); + DefaultPrettyPrinter pp = new DefaultPrettyPrinter() + .withObjectIndenter(new DefaultIndenter(" ", "\n")) + .withSeparators(separators); + String expected = _printTestData(pp, false); + assertEquals(expected, _printTestData(pp, true)); + + DefaultPrettyPrinter copy = new DefaultPrettyPrinter(pp); + assertEquals(expected, _printTestData(copy, false)); + assertEquals(expected, _printTestData(copy, true)); + } - public void testRootSeparator() throws IOException + public void testRootSeparatorOld() throws IOException { + @SuppressWarnings("deprecation") // Testing the old API DefaultPrettyPrinter pp = new DefaultPrettyPrinter() .withRootSeparator("|"); final String EXP = "1|2|3"; - StringWriter sw = new StringWriter(); - JsonGenerator gen = JSON_F.createGenerator(sw); - gen.setPrettyPrinter(pp); - - gen.writeNumber(1); - gen.writeNumber(2); - gen.writeNumber(3); - gen.close(); - assertEquals(EXP, sw.toString()); - - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - gen = JSON_F.createGenerator(bytes); - gen.setPrettyPrinter(pp); + ThrowingConsumer writeTestData = gen -> { + gen.writeNumber(1); + gen.writeNumber(2); + gen.writeNumber(3); + }; - gen.writeNumber(1); - gen.writeNumber(2); - gen.writeNumber(3); - gen.close(); - assertEquals(EXP, bytes.toString("UTF-8")); + assertEquals(EXP, _printTestData(pp, false, writeTestData)); + assertEquals(EXP, _printTestData(pp, true, writeTestData)); + } + + public void testRootSeparator() throws IOException + { + Separators separators = new Separators() + .withRootSeparator("|"); + DefaultPrettyPrinter pp = new DefaultPrettyPrinter() + .withSeparators(separators); + final String EXP = "1|2|3"; + + ThrowingConsumer writeTestData = gen -> { + gen.writeNumber(1); + gen.writeNumber(2); + gen.writeNumber(3); + }; + + assertEquals(EXP, _printTestData(pp, false, writeTestData)); + assertEquals(EXP, _printTestData(pp, true, writeTestData)); + } + public void testWithoutSeparatorsOld() throws IOException + { // Also: let's try removing separator altogether - pp = pp.withRootSeparator((String) null) + @SuppressWarnings("deprecation") // Testing the old API + DefaultPrettyPrinter pp = new DefaultPrettyPrinter() + .withRootSeparator((String) null) .withArrayIndenter(null) .withObjectIndenter(null) .withoutSpacesInObjectEntries(); - sw = new StringWriter(); - gen = JSON_F.createGenerator(sw); - gen.setPrettyPrinter(pp); - gen.writeNumber(1); - gen.writeStartArray(); - gen.writeNumber(2); - gen.writeEndArray(); - gen.writeStartObject(); - gen.writeFieldName("a"); - gen.writeNumber(3); - gen.writeEndObject(); - gen.close(); + ThrowingConsumer writeTestData = gen -> { + gen.writeNumber(1); + gen.writeStartArray(); + gen.writeNumber(2); + gen.writeEndArray(); + gen.writeStartObject(); + gen.writeFieldName("a"); + gen.writeNumber(3); + gen.writeEndObject(); + }; // no root separator, nor array, object - assertEquals("1[2]{\"a\":3}", sw.toString()); + assertEquals("1[2]{\"a\":3}", _printTestData(pp, false, writeTestData)); + } + + public void testWithoutSeparatorsNew() throws IOException + { + Separators separators = new Separators() + .withRootSeparator(null) + .withObjectFieldValueSpacing(Spacing.NONE); + DefaultPrettyPrinter pp = new DefaultPrettyPrinter() + .withSeparators(separators) + .withArrayIndenter(null) + .withObjectIndenter(null); + + ThrowingConsumer writeTestData = gen -> { + gen.writeNumber(1); + gen.writeStartArray(); + gen.writeNumber(2); + gen.writeEndArray(); + gen.writeStartObject(); + gen.writeFieldName("a"); + gen.writeNumber(3); + gen.writeEndObject(); + }; + // no root separator, nor array, object + assertEquals("1[2]{\"a\":3}", _printTestData(pp, false, writeTestData)); } private String _printTestData(PrettyPrinter pp, boolean useBytes) throws IOException + { + return _printTestData(pp, useBytes, gen -> { + gen.writeStartObject(); + gen.writeFieldName("name"); + gen.writeString("John Doe"); + gen.writeFieldName("age"); + gen.writeNumber(3.14); + gen.writeEndObject(); + }); + } + + private String _printTestData(PrettyPrinter pp, boolean useBytes, ThrowingConsumer writeTestData) throws IOException { JsonGenerator gen; StringWriter sw; ByteArrayOutputStream bytes; - + if (useBytes) { sw = null; bytes = new ByteArrayOutputStream(); @@ -146,14 +261,9 @@ private String _printTestData(PrettyPrinter pp, boolean useBytes) throws IOExcep gen = JSON_F.createGenerator(sw); } gen.setPrettyPrinter(pp); - gen.writeStartObject(); - gen.writeFieldName("name"); - gen.writeString("John Doe"); - gen.writeFieldName("age"); - gen.writeNumber(3.14); - gen.writeEndObject(); + writeTestData.accept(gen); gen.close(); - + if (useBytes) { return bytes.toString("UTF-8"); } diff --git a/src/test/java/com/fasterxml/jackson/core/write/PrettyPrinterTest.java b/src/test/java/com/fasterxml/jackson/core/write/PrettyPrinterTest.java index f8eabb70fe..05c91a4bac 100644 --- a/src/test/java/com/fasterxml/jackson/core/write/PrettyPrinterTest.java +++ b/src/test/java/com/fasterxml/jackson/core/write/PrettyPrinterTest.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.core.util.MinimalPrettyPrinter; import com.fasterxml.jackson.core.util.Separators; +import com.fasterxml.jackson.core.util.Separators.Spacing; import java.io.*; @@ -131,14 +132,33 @@ public void beforeArrayValues(JsonGenerator jg) throws IOException, JsonGenerati } // [core#26] - public void testCustomRootSeparatorWithPP() throws Exception + public void testRootSeparatorWithoutPP() throws Exception { - // first, no pretty-printing (will still separate root values with a space!) + // no pretty-printing (will still separate root values with a space!) assertEquals("{} {} []", _generateRoot(JSON_F, null)); - // First with default pretty printer, default configs: + } + + // [core#26] + public void testDefaultRootSeparatorWithPP() throws Exception + { assertEquals("{ } { } [ ]", _generateRoot(JSON_F, new DefaultPrettyPrinter())); - // then custom: - assertEquals("{ }|{ }|[ ]", _generateRoot(JSON_F, new DefaultPrettyPrinter("|"))); + } + + // [core#26] + public void testCustomRootSeparatorWithPPOld() throws Exception + { + @SuppressWarnings("deprecation") + DefaultPrettyPrinter pp = new DefaultPrettyPrinter("|"); + assertEquals("{ }|{ }|[ ]", _generateRoot(JSON_F, pp)); + } + + // [core#26] + public void testCustomRootSeparatorWithPPNew() throws Exception + { + Separators separators = Separators.createDefaultInstance() + .withRootSeparator("|"); + DefaultPrettyPrinter pp = new DefaultPrettyPrinter(separators); + assertEquals("{ }|{ }|[ ]", _generateRoot(JSON_F, pp)); } // Alternative solution for [jackson-core#26] @@ -202,25 +222,50 @@ public void testCustomSeparatorsWithPP() throws Exception "} ]", sw.toString()); } - public void testCustomSeparatorsWithPPWithoutSpaces() throws Exception + private static final String EXPECTED_CUSTOM_SEPARATORS_WITH_PP_WITHOUT_SPACES = + "[ 3| \"abc\"| [ true ]| {" + DefaultIndenter.SYS_LF + + " \"f\"=null;" + DefaultIndenter.SYS_LF + + " \"f2\"=null" + DefaultIndenter.SYS_LF + + "} ]"; + + public void testCustomSeparatorsWithPPWithoutSpacesOld() throws Exception { StringWriter sw = new StringWriter(); JsonGenerator gen = new JsonFactory().createGenerator(sw); - gen.setPrettyPrinter(new DefaultPrettyPrinter().withSeparators(Separators.createDefaultInstance() + Separators separators = Separators.createDefaultInstance() .withObjectFieldValueSeparator('=') .withObjectEntrySeparator(';') - .withArrayValueSeparator('|')) - .withoutSpacesInObjectEntries()); + .withArrayValueSeparator('|'); + @SuppressWarnings("deprecation") + DefaultPrettyPrinter pp = new DefaultPrettyPrinter() + .withSeparators(separators) + .withoutSpacesInObjectEntries(); + gen.setPrettyPrinter(pp); _writeTestDocument(gen); gen.close(); - assertEquals("[ 3| \"abc\"| [ true ]| {" + DefaultIndenter.SYS_LF + - " \"f\"=null;" + DefaultIndenter.SYS_LF + - " \"f2\"=null" + DefaultIndenter.SYS_LF + - "} ]", sw.toString()); + assertEquals(EXPECTED_CUSTOM_SEPARATORS_WITH_PP_WITHOUT_SPACES, sw.toString()); } + public void testCustomSeparatorsWithPPWithoutSpacesNew() throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createGenerator(sw); + Separators separators = Separators.createDefaultInstance() + .withObjectFieldValueSeparator('=') + .withObjectFieldValueSpacing(Spacing.NONE) + .withObjectEntrySeparator(';') + .withArrayValueSeparator('|'); + DefaultPrettyPrinter pp = new DefaultPrettyPrinter(separators); + gen.setPrettyPrinter(pp); + + _writeTestDocument(gen); + gen.close(); + + assertEquals(EXPECTED_CUSTOM_SEPARATORS_WITH_PP_WITHOUT_SPACES, sw.toString()); + } + /* /********************************************************** /* Helper methods