diff --git a/src/main/java/com/fasterxml/jackson/dataformat/xml/util/DefaultXmlPrettyPrinter.java b/src/main/java/com/fasterxml/jackson/dataformat/xml/util/DefaultXmlPrettyPrinter.java index a0c0bbb61..aca070536 100644 --- a/src/main/java/com/fasterxml/jackson/dataformat/xml/util/DefaultXmlPrettyPrinter.java +++ b/src/main/java/com/fasterxml/jackson/dataformat/xml/util/DefaultXmlPrettyPrinter.java @@ -77,6 +77,27 @@ public interface Indenter */ protected boolean _spacesInObjectEntries = true; + /** + * By default, will try to set as System.getProperty("line.separator"). + * Can later set custom new line with withCustomNewLine method. + * @since 2.15 + */ + private static final String SYSTEM_DEFAULT_NEW_LINE; + static { + String lf = null; + try { + lf = System.getProperty("line.separator"); + } catch (Exception t) { } // access exception? + SYSTEM_DEFAULT_NEW_LINE = lf; + } + protected String _newLine = SYSTEM_DEFAULT_NEW_LINE; + + static final int SPACE_COUNT = 64; + static final char[] SPACES = new char[SPACE_COUNT]; + static { + Arrays.fill(SPACES, ' '); + } + /* /********************************************************** /* State @@ -112,6 +133,7 @@ protected DefaultXmlPrettyPrinter(DefaultXmlPrettyPrinter base) _objectIndenter = base._objectIndenter; _spacesInObjectEntries = base._spacesInObjectEntries; _nesting = base._nesting; + _newLine = base._newLine; } public void indentArraysWith(Indenter i) @@ -126,6 +148,15 @@ public void indentObjectsWith(Indenter i) public void spacesInObjectEntries(boolean b) { _spacesInObjectEntries = b; } + /** + * Sets custom new-line. + * @since 2.15 + */ + public DefaultXmlPrettyPrinter withCustomNewLine(String newLine) { + _newLine = newLine != null ? newLine : SYSTEM_DEFAULT_NEW_LINE; + return this; + } + /* /********************************************************** /* Instantiatable impl @@ -443,7 +474,7 @@ public void writeLeafXsiNilElement(XMLStreamWriter2 sw, public void writePrologLinefeed(XMLStreamWriter2 sw) throws XMLStreamException { // 06-Dec-2015, tatu: Alternatively could try calling `writeSpace()`... - sw.writeRaw(Lf2SpacesIndenter.SYSTEM_LINE_SEPARATOR); + sw.writeRaw(_newLine); } /* @@ -486,7 +517,7 @@ public void writeIndentation(XMLStreamWriter2 sw, int level) { sw.writeRaw(" "); } - + @Override public void writeIndentation(JsonGenerator g, int level) throws IOException { @@ -501,26 +532,11 @@ public void writeIndentation(JsonGenerator g, int level) throws IOException * Default linefeed-based indenter uses system-specific linefeeds and * 2 spaces for indentation per level. */ - protected static class Lf2SpacesIndenter + protected class Lf2SpacesIndenter implements Indenter, java.io.Serializable { private static final long serialVersionUID = 1L; - final static String SYSTEM_LINE_SEPARATOR; - static { - String lf = null; - try { - lf = System.getProperty("line.separator"); - } catch (Throwable t) { } // access exception? - SYSTEM_LINE_SEPARATOR = (lf == null) ? "\n" : lf; - } - - final static int SPACE_COUNT = 64; - final static char[] SPACES = new char[SPACE_COUNT]; - static { - Arrays.fill(SPACES, ' '); - } - public Lf2SpacesIndenter() { } @Override @@ -529,7 +545,7 @@ public Lf2SpacesIndenter() { } @Override public void writeIndentation(XMLStreamWriter2 sw, int level) throws XMLStreamException { - sw.writeRaw(SYSTEM_LINE_SEPARATOR); + sw.writeRaw(_newLine); level += level; // 2 spaces per level while (level > SPACE_COUNT) { // should never happen but... sw.writeRaw(SPACES, 0, SPACE_COUNT); @@ -541,7 +557,7 @@ public void writeIndentation(XMLStreamWriter2 sw, int level) throws XMLStreamExc @Override public void writeIndentation(JsonGenerator jg, int level) throws IOException { - jg.writeRaw(SYSTEM_LINE_SEPARATOR); + jg.writeRaw(_newLine); level += level; // 2 spaces per level while (level > SPACE_COUNT) { // should never happen but... jg.writeRaw(SPACES, 0, SPACE_COUNT); diff --git a/src/test/java/com/fasterxml/jackson/dataformat/xml/ser/XmlPrettyPrinterTest.java b/src/test/java/com/fasterxml/jackson/dataformat/xml/ser/XmlPrettyPrinterTest.java index bc0aa59a5..d7f76dce3 100644 --- a/src/test/java/com/fasterxml/jackson/dataformat/xml/ser/XmlPrettyPrinterTest.java +++ b/src/test/java/com/fasterxml/jackson/dataformat/xml/ser/XmlPrettyPrinterTest.java @@ -4,24 +4,26 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.core.PrettyPrinter; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlTestBase; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter; public class XmlPrettyPrinterTest extends XmlTestBase { static class StringWrapperBean { public StringWrapper string; - + public StringWrapperBean() { } public StringWrapperBean(String s) { string = new StringWrapper(s); } } static class IntWrapperBean { public IntWrapper wrapped; - + public IntWrapperBean() { } public IntWrapperBean(int i) { wrapped = new IntWrapper(i); } } @@ -44,11 +46,11 @@ public class PojoFor123 @JacksonXmlProperty(isAttribute = true) public String name; - @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonInclude(JsonInclude.Include.NON_EMPTY) public String property; public PojoFor123(String name) { - this.name = name; + this.name = name; } } @@ -89,6 +91,8 @@ public void setUp() throws Exception { _xmlMapper.configure(SerializationFeature.INDENT_OUTPUT, true); } + private static final String SYSTEM_DEFAULT_NEW_LINE = System.getProperty("line.separator"); + /* /********************************************************** /* Unit tests @@ -176,16 +180,90 @@ public void testMultiLevel172() throws Exception .writeValueAsString(root); // unify possible apostrophes to quotes xml = a2q(xml); - // with indentation, should get linefeeds in prolog/epilog too - assertEquals("\n" - +"\n" - +" \n" - +" \n" - +" abc\n" - +" FULL_TIME\n" - +" \n" - +" \n" - +"\n", + + assertEquals("" + SYSTEM_DEFAULT_NEW_LINE + +"" + SYSTEM_DEFAULT_NEW_LINE + +" " + SYSTEM_DEFAULT_NEW_LINE + +" " + SYSTEM_DEFAULT_NEW_LINE + +" abc" + SYSTEM_DEFAULT_NEW_LINE + +" FULL_TIME" + SYSTEM_DEFAULT_NEW_LINE + +" " + SYSTEM_DEFAULT_NEW_LINE + +" " + SYSTEM_DEFAULT_NEW_LINE + +"" + SYSTEM_DEFAULT_NEW_LINE, xml); } + + public void testNewLine_withCustomNewLine() throws Exception { + String customNewLine = "\n\rLF\n\r"; + PrettyPrinter customXmlPrettyPrinter = new DefaultXmlPrettyPrinter().withCustomNewLine(customNewLine); + + Company root = new Company(); + root.employee.add(new Employee("abc")); + + String xml = _xmlMapper.writer() + .with(customXmlPrettyPrinter) + .with(ToXmlGenerator.Feature.WRITE_XML_DECLARATION) + .writeValueAsString(root); + // unify possible apostrophes to quotes + xml = a2q(xml); + + // with indentation, should get newLines in prolog/epilog too + assertEquals("" + customNewLine + + "" + customNewLine + + " " + customNewLine + + " " + customNewLine + + " abc" + customNewLine + + " FULL_TIME" + customNewLine + + " " + customNewLine + + " " + customNewLine + + "" + customNewLine, + xml); + } + + public void testNewLine_systemDefault() throws Exception { + Company root = new Company(); + root.employee.add(new Employee("abc")); + + String xml = _xmlMapper.writer() + .with(new DefaultXmlPrettyPrinter()) + .with(ToXmlGenerator.Feature.WRITE_XML_DECLARATION) + .writeValueAsString(root); + // unify possible apostrophes to quotes + xml = a2q(xml); + + // with indentation, should get newLines in prolog/epilog too + assertEquals("" + SYSTEM_DEFAULT_NEW_LINE + + "" + SYSTEM_DEFAULT_NEW_LINE + + " " + SYSTEM_DEFAULT_NEW_LINE + + " " + SYSTEM_DEFAULT_NEW_LINE + + " abc" + SYSTEM_DEFAULT_NEW_LINE + + " FULL_TIME" + SYSTEM_DEFAULT_NEW_LINE + + " " + SYSTEM_DEFAULT_NEW_LINE + + " " + SYSTEM_DEFAULT_NEW_LINE + + "" + SYSTEM_DEFAULT_NEW_LINE, + xml); + } + + public void testNewLine_UseSystemDefaultLineSeperatorOnNullCustomNewLine() throws Exception { + Company root = new Company(); + root.employee.add(new Employee("abc")); + + String xml = _xmlMapper.writer() + .with(new DefaultXmlPrettyPrinter().withCustomNewLine(null)) + .with(ToXmlGenerator.Feature.WRITE_XML_DECLARATION) + .writeValueAsString(root); + // unify possible apostrophes to quotes + xml = a2q(xml); + + assertEquals("" + SYSTEM_DEFAULT_NEW_LINE + + "" + SYSTEM_DEFAULT_NEW_LINE + + " " + SYSTEM_DEFAULT_NEW_LINE + + " " + SYSTEM_DEFAULT_NEW_LINE + + " abc" + SYSTEM_DEFAULT_NEW_LINE + + " FULL_TIME" + SYSTEM_DEFAULT_NEW_LINE + + " " + SYSTEM_DEFAULT_NEW_LINE + + " " + SYSTEM_DEFAULT_NEW_LINE + + "" + SYSTEM_DEFAULT_NEW_LINE, + xml); + } }