Skip to content

Introduce JSON pretty print #13357

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

Draft
wants to merge 1 commit into
base: jetty-12.1.x
Choose a base branch
from

Conversation

arsenalzp
Copy link
Contributor

@arsenalzp arsenalzp commented Jul 16, 2025

This is draft PR for issue #13318.

Signed-off-by: Oleksandr Krutko <alexander.krutko@gmail.com>
@arsenalzp arsenalzp changed the base branch from jetty-12.0.x to jetty-12.1.x July 16, 2025 18:46
@joakime joakime requested a review from sbordet July 16, 2025 19:31
@joakime joakime marked this pull request as draft July 16, 2025 19:32
@joakime joakime moved this to 🏗 In progress in Jetty 12.1.1 Jul 16, 2025
Copy link
Contributor

@gregw gregw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good start.
However a unitTest will most definitely be needed

return toString(o, ident, 0);
}

private String toString(final Object o, String ident, int nest)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably needs loop protection. I'm sure it is not legal json for a map/array to contain itself, but somebody will create one and pass it. Throwing early is better than stack overflow, or even just print a name instead of the contents in a loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need importing additional package for such simple operation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need importing additional package for such simple operation?

I think this reply is for the StringUtil comment.

No new package needed, you have access to it already in jetty-util-AJAX.

https://github.com/jetty/jetty.project/blob/jetty-12.0.x/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably needs loop protection. I'm sure it is not legal json for a map/array to contain itself, but somebody will create one and pass it. Throwing early is better than stack overflow, or even just print a name instead of the contents in a loop.

There's no loop protection in the existing String JSON.toJSON(Object obj), why would we need it here?
This PR is just about pretty printing, indents and whatnot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need importing additional package for such simple operation?

I think this reply is for the StringUtil comment.

No new package needed, you have access to it already in jetty-util-AJAX.

https://github.com/jetty/jetty.project/blob/jetty-12.0.x/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java

I will check. Thank you!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't understand why this is suddenly a requirement for jetty-util-ajax.
Just so you know, infinite recursion, stackoverflows, etc are not guarded against in jackson, org.json, or gson. (probably the 3 most used json libs in the java world).
The reason is that it causes too much memory use.
The solution for infinite recursion during serialization in libs like spring, hibernate, and jackson is to annotate specific entries to solve the recursion, not to build in object instance tracking into the serialization.

https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion

Anyway, a visited Set is probably the wrong approach.
After all the same object can be in the Map in different locations safely.
A Stack is better, as it's only about what's references are above the current state that you care about, but that would need to be passed around to be sane.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not suddenly a requirement, just a thought whilst we are touching this class.

If the pretty printer to be used in generating real json as part of an app? Then let's not waste the memory.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jackson now has protection FasterXML/jackson-core#943 against this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jackson now has protection FasterXML/jackson-core#943 against this.

That solution doesn't have duplicate object instance tracking, it just sets a maximum depth of nesting content.
That's not a bad idea actually, instead of duplicate object tracking via a collection, just set a maximum depth configurable instead. Same end result, no more StackOverFlowExceptions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello,
I checked JSON spec, there is no limitation of nested objects, so it is dependent on platform and available resources.

return array.toString();
}

private String putQuote(Object o)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StringUtil has methods that do this... check if they are usable or not

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jetty's StringUtil doesn't have such a method.

Why not just implement this using an Appendable and reusing the existing JSON.quotedEscape(Appendable buffer, String input) for this purpose instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, I was thinking about org.eclipse.jetty.http.QuotedCSVParser#quoteIfNeeded

@arsenalzp
Copy link
Contributor Author

Good start. However a unitTest will most definitely be needed

That's for sure!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 🏗 In progress
Development

Successfully merging this pull request may close these issues.

4 participants