-
-
Notifications
You must be signed in to change notification settings - Fork 228
Feature : Allow setting custom linefeed on DefaultXmlPrettyPrinter #568
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature : Allow setting custom linefeed on DefaultXmlPrettyPrinter #568
Conversation
src/main/java/com/fasterxml/jackson/dataformat/xml/util/DefaultXmlPrettyPrinter.java
Show resolved
Hide resolved
src/main/java/com/fasterxml/jackson/dataformat/xml/util/DefaultXmlPrettyPrinter.java
Outdated
Show resolved
Hide resolved
src/main/java/com/fasterxml/jackson/dataformat/xml/util/DefaultXmlPrettyPrinter.java
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
protected static String _lineFeed = DEFAULT_LINE_FEED; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protected String _lineFeed = DEFAULT_LINE_FEED;
-- should not be static
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pjfanning I have a question.
Even if we make _lineFeed
field non-static, we have static line-feeding Indenters like Lf2SpacesIndenter
. Linefeed happens inside Lf2SpacesIndenter.writeIndentation()
.
So Indenters can't access non-static field of outer class. 🥲
How can we solve this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thoughts, line-feed outside of Lf2SpacesIndenter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lf2SpacesIndenter could have a constructor that takes an instance of DefaultXmlPrettyPrinter in its constructor. Or we could make Lf2SpacesIndenter non-static.
I have to ask why you are not ensuring the code compiles? The |
|
xml = a2q(xml); | ||
|
||
// with indentation, should get linefeeds in prolog/epilog too | ||
assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if this line should end with customLineFeed instead of `\n?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see the answer to your follow up question
+ " <type>FULL_TIME</type>\n\rLF\n\r" | ||
+ " </employee>\n\rLF\n\r" | ||
+ " </e>\n\rLF\n\r" | ||
+ "</Company>\n", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if this line should end with customLineFeed instead of `\n?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes - all the line feeds should be the same
actually, could we rename the method as withCustomNewLine
? - I don't think 'line feed' is a good name for this property at all - 'new line' is better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes - all the line feeds should be the same
noted will make sure tests are applied there?
actually, could we rename the method as withCustomNewLine? - I don't think 'line feed' is a good name for this property at all - 'new line' is better
Agreed and I will change names as below!🙏🏼
_lineFeed
->_newLine
DEFAULT_LINE_FEED
->SYSTEM_DEFAULT_NEW_LINE
withCustomLineFeed
->withCustomNewLine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pjfanning So here is an update.
actually, could we rename the method as withCustomNewLine? - I don't think 'line feed' is a good name for this property at all - 'new line' is better
Done.
All names are changed from 'line feed' to 'new line'
yes - all the line feeds should be the same
May I get your opinion here? It seems like writing custom 'new lines' before and after root element might be out of this PR's scope. The 'new lines' before and after the root element are written by method writePrologLinefeed()
of another instance of DefaultXmlPrettyPrinter
.
This instance invoking writePrologLinefeed()
instance seems to be initialized and used inside ToXmlGenerator which we cannot hook into from neither XmlMapper().setDefaultPrettyPrinter()
nor ObjectWriter.with(PrettyPrinter)
.
For references,
- Similar issues I found doing research. Removed prolog line feed in XMLPrettyPrinter as the current version m… #554
- Check 👉🏼 the code here writes BEFORE root element and the code here writes AFTER root element
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes little sense to me not to use the same new lines throughout the XML doc. I'm now -1 on this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JooHyukKim Ok that sounds like a problem indeed! I wonder if it's the case of Indenter
instance not being created yet (with createInstance()
) or what is happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not the indenter, actually. There is a separate instance of DefaultXmlPrettyPrinter
initialized together with ToXmlGenerator
that invokes _xmlPrettyPrinter.writePrologLinefeed
to write prolog and epilog.
You can refer to below to code lines.
- ToXmlGenerator. initGenerator method for prolog and
- ToXmlGenerator._handleObject for epilog
My first (probable) observation is that writing prolog and epilog with instance of DefaultXmlPrettyPrinter
I mentioned above seems NOT to be overridden by ObjectMapper.setDefaultPrettyPrinter(PrettyPrinter)
nor ObjectWriter.with(PrettyPrinter)
.
Second observation is ToXmlGenerator
writes prolog during the process of initialization within ToXmlGenerator.initGenerator
method.
It will be great, @cowtowncoder if you can help out a little here? To override DefaultXmlPrettyPrinter of ToXmlGenerator._xmlPrettyPrinter
before it writes prolog and epilog?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, pretty printer instance. I will try to see if I can figure it out -- the problem is that XML module extends basic PrettyPrinter
API to its needs but databind still tries to orchestrate handling. So I will try to see if I can figure out how to avoid there being different instance being used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JooHyukKim Ah. Part of the problem is that you haven't updated copy constructor:
protected DefaultXmlPrettyPrinter(DefaultXmlPrettyPrinter base) { }
to copy _newLine
property -- so when method
@Override
public DefaultXmlPrettyPrinter createInstance() {
is called the new instance "forgets" _newLine
. So you need to add
_newLine = base._newLine;
in that constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is called the new instance "forgets"
_newLine
. So you need to add
Woooooow thank you for helping out 🥹 @cowtowncoder
How did I miss that!
Done 🙏🏼
* @since 2.15 | ||
*/ | ||
public DefaultXmlPrettyPrinter withCustomNewLine(String newLine) { | ||
// 06-Feb-2023, joohyukkim: when JacksonException extends RuntimeExceptions, throw it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you remove this comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done :)
+ " <type>FULL_TIME</type>\n\rLF\n\r" | ||
+ " </employee>\n\rLF\n\r" | ||
+ " </e>\n\rLF\n\r" | ||
+ "</Company>\n", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes little sense to me not to use the same new lines throughout the XML doc. I'm now -1 on this PR.
src/main/java/com/fasterxml/jackson/dataformat/xml/util/DefaultXmlPrettyPrinter.java
Outdated
Show resolved
Hide resolved
String lf = null; | ||
try { | ||
lf = System.getProperty("line.separator"); | ||
} catch (Throwable t) { } // access exception? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's just catch Exception
, not Throwable
(ok unlike we'd get OOME or such but as a general good practice)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
late reply, but done 👍🏻
src/main/java/com/fasterxml/jackson/dataformat/xml/util/DefaultXmlPrettyPrinter.java
Outdated
Show resolved
Hide resolved
@@ -473,7 +501,7 @@ public NopIndenter() { } | |||
* single space for indentation. It is used as the default | |||
* indenter for array values. | |||
*/ | |||
protected static class FixedSpaceIndenter | |||
protected class FixedSpaceIndenter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, keep static
(no need to refer to enclosing class)
src/main/java/com/fasterxml/jackson/dataformat/xml/util/DefaultXmlPrettyPrinter.java
Outdated
Show resolved
Hide resolved
Sorry it took me long to react! 🙏🏼 I just got internet back, I will try to apply your feed back asap. |
All reviews made up to this point are applied to the changes. The only thing left is being discussed in the thread of comments above. Simply put, about how to(or whether) to apply custom new line while writing XML declaration with |
xml = a2q(xml); | ||
|
||
// with indentation, should get newLines in prolog/epilog too | ||
assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to replace \n
with system linefeed so test passes on Windows systems too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, done! 🙏🏼
And plus I checked other similar test cases' assertions and some hard coded \n
as system linefeed.
@cowtowncoder if you agree, I will make a separate PR on "replacing all hard coded \n
to the value read from System.getProperty("line.separator");
"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah sounds good wrt hard-coded linefeeds
*/ | ||
public DefaultXmlPrettyPrinter withCustomNewLine(String newLine) { | ||
if (newLine != null) { | ||
_newLine = newLine; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not set _newLine
to SYSTEM_DEFAULT_NEW_LINE
if null
is passed? This would allow reverting back to system newline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I don't see any problem doing so.
done!
Thank you again @JooHyukKim ! Merged for inclusion in 2.15.0 |
DefaultXmlPrettyPrinter.withCustomNewLine()
to configure linefeed for XML pretty-printing #560BEFORE
static { }
block fromLf2SpacesIndenter
is run.DefaultXmlPrettyPrinter
andIndenters
both use staticLf2SpacesIndenter.SYSTEM_LINE_SEPARATOR
AFTER
_lineFeed
is set whenstatic { }
block fromDefaultXmlPrettyPrinter
is run.Indenters
ONLY customize indentations and linefeed value is given byDefaultXmlPrettyPrinter