From 97892ff273ff0d75b1b33e15332c3d15430b7d9f Mon Sep 17 00:00:00 2001 From: jbb01 <32650546+jbb01@users.noreply.github.com> Date: Sat, 12 Apr 2025 19:51:42 +0200 Subject: [PATCH] allow JsonArray to pretty-print in a single line when appropriate --- .../java/eu/jonahbauer/json/JsonArray.java | 25 +++++++++++++++---- .../java/eu/jonahbauer/json/JsonObject.java | 13 +++++++--- .../java/eu/jonahbauer/json/JsonValue.java | 19 +++++++++++++- .../main/java/eu/jonahbauer/json/Util.java | 3 +++ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/eu/jonahbauer/json/JsonArray.java b/core/src/main/java/eu/jonahbauer/json/JsonArray.java index 20fb659..198d80f 100644 --- a/core/src/main/java/eu/jonahbauer/json/JsonArray.java +++ b/core/src/main/java/eu/jonahbauer/json/JsonArray.java @@ -370,12 +370,27 @@ public record JsonArray( } @Override - public @NotNull String toPrettyJsonString() { + public @NotNull String toPrettyJsonString(int depth) { if (size() < 2) return toJsonString(); - var out = new StringJoiner(",\n", "[\n", "\n]"); - elements().forEach(e -> out.add(indent(JsonValue.toPrettyJsonString(e)))); - return out.toString(); + var entries = new ArrayList(elements.size()); + var length = 0L; + var composite = false; + for (var element : elements) { + var string = JsonValue.toPrettyJsonString(element, depth + Util.PRETTY_PRINT_INDENT.length()); + entries.add(string); + + composite |= element instanceof JsonObject || element instanceof JsonArray; + length += string.length() + 2; // +2 to account for ", " and "[]" + } + + if (!composite && depth + length <= Util.PRETTY_PRINT_ARRAY_MULTILINE_THRESHOLD) { + return "[" + String.join(", ", entries) + "]"; + } else { + var out = new StringJoiner(",\n", "[\n", "\n]"); + entries.forEach(e -> out.add(indent(e))); + return out.toString(); + } } private static @NotNull String indent(@NotNull String string) { @@ -385,7 +400,7 @@ public record JsonArray( Iterator it = string.lines().iterator(); while (it.hasNext()) { - out.append(" ").append(it.next()); + out.append(Util.PRETTY_PRINT_INDENT).append(it.next()); if (it.hasNext()) out.append('\n'); } diff --git a/core/src/main/java/eu/jonahbauer/json/JsonObject.java b/core/src/main/java/eu/jonahbauer/json/JsonObject.java index 11423ff..32f1508 100644 --- a/core/src/main/java/eu/jonahbauer/json/JsonObject.java +++ b/core/src/main/java/eu/jonahbauer/json/JsonObject.java @@ -353,9 +353,14 @@ public record JsonObject(@NotNull Map<@NotNull String, @Nullable JsonValue> entr } @Override - public @NotNull String toPrettyJsonString() { - StringJoiner out = new StringJoiner(",\n ", "{\n ", "\n}"); - entries.forEach((key, value) -> out.add(JsonString.quote(key) + ": " + indent(JsonValue.toPrettyJsonString(value)))); + public @NotNull String toPrettyJsonString(int depth) { + StringJoiner out = new StringJoiner(",\n" + Util.PRETTY_PRINT_INDENT, "{\n" + Util.PRETTY_PRINT_INDENT, "\n}"); + entries.forEach((key, value) -> { + var keyString = JsonString.quote(key); + var valueIdent = depth + Util.PRETTY_PRINT_INDENT.length() + keyString.length() + 3; // +3 for ": " and "," + var valueString = JsonValue.toPrettyJsonString(value, valueIdent); + out.add(keyString + ": " + indent(valueString)); + }); return out.toString(); } @@ -369,7 +374,7 @@ public record JsonObject(@NotNull Map<@NotNull String, @Nullable JsonValue> entr while (it.hasNext()) { String next = it.next(); - out.append('\n').append(it.hasNext() ? " " : " ").append(next); + out.append('\n').append(Util.PRETTY_PRINT_INDENT).append(next); } return out.toString(); diff --git a/core/src/main/java/eu/jonahbauer/json/JsonValue.java b/core/src/main/java/eu/jonahbauer/json/JsonValue.java index 8cf64fa..587bfcb 100644 --- a/core/src/main/java/eu/jonahbauer/json/JsonValue.java +++ b/core/src/main/java/eu/jonahbauer/json/JsonValue.java @@ -24,6 +24,14 @@ public sealed interface JsonValue extends Serializable permits JsonObject, JsonA * {@return a prettified JSON representation of this value} */ default @NotNull String toPrettyJsonString() { + return toPrettyJsonString(0); + } + + /** + * {@return a prettified JSON representation of this value} + * @param depth indicates the depth at which this value appears (no formal definition given) + */ + default @NotNull String toPrettyJsonString(int depth) { return toJsonString(); } @@ -40,7 +48,16 @@ public sealed interface JsonValue extends Serializable permits JsonObject, JsonA * @param value a {@link JsonValue} (possibly {@code null}) */ static @NotNull String toPrettyJsonString(@Nullable JsonValue value) { - return value == null ? "null" : value.toPrettyJsonString(); + return toPrettyJsonString(value, 0); + } + + /** + * {@return the prettified JSON representation of the given value} + * @param value a {@link JsonValue} (possibly {@code null}) + * @param depth indicates the depth at which the value appears (no formal definition given) + */ + static @NotNull String toPrettyJsonString(@Nullable JsonValue value, int depth) { + return value == null ? "null" : value.toPrettyJsonString(depth); } /** diff --git a/core/src/main/java/eu/jonahbauer/json/Util.java b/core/src/main/java/eu/jonahbauer/json/Util.java index 2f3f9d4..872b797 100644 --- a/core/src/main/java/eu/jonahbauer/json/Util.java +++ b/core/src/main/java/eu/jonahbauer/json/Util.java @@ -8,6 +8,9 @@ import java.util.*; @UtilityClass class Util { + static final @NotNull String PRETTY_PRINT_INDENT = " "; + static final int PRETTY_PRINT_ARRAY_MULTILINE_THRESHOLD = 80; + private static final @NotNull Class LIST_1_2 = List.of(1).getClass(); private static final @NotNull Class LIST_N = List.of(1, 2, 3).getClass(); private static final @NotNull Class SUB_LIST = List.of(1, 2, 3).subList(0, 2).getClass();