Skip to content

Commit 80e79f1

Browse files
authored
Allow configuring DefaultPrettyPrinter separators for empty Arrays and Objects (#1178)
1 parent 717cd6b commit 80e79f1

File tree

5 files changed

+224
-18
lines changed

5 files changed

+224
-18
lines changed

release-notes/CREDITS-2.x

+5
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,8 @@ Robert Elliot (@Mahoney)
415415
(2.17.0)
416416
* Reported #1168: `JsonPointer.append(JsonPointer.tail())` includes the original pointer
417417
(2.16.1)
418+
419+
Guillaume Lecroc (@gulecroc)
420+
* Contributed #1179: Allow configuring `DefaultPrettyPrinter` separators for empty
421+
Arrays and Objects
422+
(2.17.0)

release-notes/VERSION-2.x

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ a pure JSON library.
2222
(contributed by @pjfanning)
2323
#1169: `ArrayIndexOutOfBoundsException` for specific invalid content,
2424
with Reader-based parser
25+
#1179: Allow configuring `DefaultPrettyPrinter` separators for empty
26+
Arrays and Objects
27+
(contributed by Guillaume L)
2528

2629
2.16.2 (not yet released)
2730

src/main/java/com/fasterxml/jackson/core/util/DefaultPrettyPrinter.java

+33-9
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,26 @@ public interface Indenter
110110
*/
111111
protected String _objectEntrySeparator;
112112

113+
/**
114+
* String to use in empty Object to separate start and end markers.
115+
* Default is single space, resulting in output of {@code { }}.
116+
*
117+
* @since 2.17
118+
*/
119+
protected String _objectEmptySeparator;
120+
113121
/**
114122
* @since 2.16
115123
*/
116124
protected String _arrayValueSeparator;
125+
126+
/**
127+
* String to use in empty Array to separate start and end markers.
128+
* Default is single space, resulting in output of {@code [ ]}.
129+
*
130+
* @since 2.17
131+
*/
132+
protected String _arrayEmptySeparator;
117133

118134
/*
119135
/**********************************************************
@@ -135,7 +151,7 @@ public DefaultPrettyPrinter() {
135151
* @param rootSeparator String to use as root value separator
136152
* @deprecated in 2.16. Use the Separators API instead.
137153
*/
138-
@Deprecated
154+
@Deprecated // since 2.16
139155
public DefaultPrettyPrinter(String rootSeparator) {
140156
this((rootSeparator == null) ? null : new SerializedString(rootSeparator));
141157
}
@@ -147,15 +163,15 @@ public DefaultPrettyPrinter(String rootSeparator) {
147163
* @param rootSeparator String to use as root value separator
148164
* @deprecated in 2.16. Use the Separators API instead.
149165
*/
150-
@Deprecated
166+
@Deprecated // since 2.16
151167
public DefaultPrettyPrinter(SerializableString rootSeparator) {
152168
this(DEFAULT_SEPARATORS.withRootSeparator(rootSeparator.getValue()));
153169
}
154170

155171
/**
156172
* @deprecated in 2.16. Use the Separators API instead.
157173
*/
158-
@Deprecated
174+
@Deprecated // since 2.16
159175
public DefaultPrettyPrinter(DefaultPrettyPrinter base,
160176
SerializableString rootSeparator)
161177
{
@@ -167,7 +183,9 @@ public DefaultPrettyPrinter(DefaultPrettyPrinter base,
167183
_separators = base._separators;
168184
_objectFieldValueSeparatorWithSpaces = base._objectFieldValueSeparatorWithSpaces;
169185
_objectEntrySeparator = base._objectEntrySeparator;
186+
_objectEmptySeparator = base._objectEmptySeparator;
170187
_arrayValueSeparator = base._arrayValueSeparator;
188+
_arrayEmptySeparator = base._arrayEmptySeparator;
171189

172190
_rootSeparator = rootSeparator;
173191
}
@@ -183,7 +201,9 @@ public DefaultPrettyPrinter(Separators separators)
183201
_objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSpacing().apply(
184202
separators.getObjectFieldValueSeparator());
185203
_objectEntrySeparator = separators.getObjectEntrySpacing().apply(separators.getObjectEntrySeparator());
204+
_objectEmptySeparator = separators.getObjectEmptySeparator();
186205
_arrayValueSeparator = separators.getArrayValueSpacing().apply(separators.getArrayValueSeparator());
206+
_arrayEmptySeparator = separators.getArrayEmptySeparator();
187207
}
188208

189209
/**
@@ -202,13 +222,15 @@ public DefaultPrettyPrinter(DefaultPrettyPrinter base) {
202222
_separators = base._separators;
203223
_objectFieldValueSeparatorWithSpaces = base._objectFieldValueSeparatorWithSpaces;
204224
_objectEntrySeparator = base._objectEntrySeparator;
225+
_objectEmptySeparator = base._objectEmptySeparator;
205226
_arrayValueSeparator = base._arrayValueSeparator;
227+
_arrayEmptySeparator = base._arrayEmptySeparator;
206228
}
207229

208230
/**
209231
* @deprecated in 2.16. Use the Separators API instead.
210232
*/
211-
@Deprecated
233+
@Deprecated // since 2.16
212234
public DefaultPrettyPrinter withRootSeparator(SerializableString rootSeparator)
213235
{
214236
if (_rootSeparator == rootSeparator ||
@@ -228,7 +250,7 @@ public DefaultPrettyPrinter withRootSeparator(SerializableString rootSeparator)
228250
* @since 2.6
229251
* @deprecated in 2.16. Use the Separators API instead.
230252
*/
231-
@Deprecated
253+
@Deprecated // since 2.16
232254
public DefaultPrettyPrinter withRootSeparator(String rootSeparator) {
233255
return withRootSeparator((rootSeparator == null) ? null : new SerializedString(rootSeparator));
234256
}
@@ -278,7 +300,7 @@ public DefaultPrettyPrinter withObjectIndenter(Indenter i) {
278300
* @since 2.3
279301
* @deprecated in 2.16. Use the Separators API instead.
280302
*/
281-
@Deprecated
303+
@Deprecated // since 2.16
282304
public DefaultPrettyPrinter withSpacesInObjectEntries() {
283305
return _withSpaces(true);
284306
}
@@ -294,7 +316,7 @@ public DefaultPrettyPrinter withSpacesInObjectEntries() {
294316
* @since 2.3
295317
* @deprecated in 2.16. Use the Separators API instead.
296318
*/
297-
@Deprecated
319+
@Deprecated // since 2.16
298320
public DefaultPrettyPrinter withoutSpacesInObjectEntries() {
299321
return _withSpaces(false);
300322
}
@@ -328,7 +350,9 @@ public DefaultPrettyPrinter withSeparators(Separators separators) {
328350
result._objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSpacing().apply(
329351
separators.getObjectFieldValueSeparator());
330352
result._objectEntrySeparator = separators.getObjectEntrySpacing().apply(separators.getObjectEntrySeparator());
353+
result._objectEmptySeparator = separators.getObjectEmptySeparator();
331354
result._arrayValueSeparator = separators.getArrayValueSpacing().apply(separators.getArrayValueSeparator());
355+
result._arrayEmptySeparator = separators.getArrayEmptySeparator();
332356

333357
return result;
334358
}
@@ -417,7 +441,7 @@ public void writeEndObject(JsonGenerator g, int nrOfEntries) throws IOException
417441
if (nrOfEntries > 0) {
418442
_objectIndenter.writeIndentation(g, _nesting);
419443
} else {
420-
g.writeRaw(' ');
444+
g.writeRaw(_objectEmptySeparator);
421445
}
422446
g.writeRaw('}');
423447
}
@@ -461,7 +485,7 @@ public void writeEndArray(JsonGenerator g, int nrOfValues) throws IOException
461485
if (nrOfValues > 0) {
462486
_arrayIndenter.writeIndentation(g, _nesting);
463487
} else {
464-
g.writeRaw(' ');
488+
g.writeRaw(_arrayEmptySeparator);
465489
}
466490
g.writeRaw(']');
467491
}

src/main/java/com/fasterxml/jackson/core/util/Separators.java

+97-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.fasterxml.jackson.core.util;
22

33
import java.io.Serializable;
4+
import java.util.Objects;
45

56
/**
67
* Value class used with some {@link com.fasterxml.jackson.core.PrettyPrinter}
@@ -23,6 +24,22 @@ public class Separators implements Serializable
2324
*/
2425
public final static String DEFAULT_ROOT_VALUE_SEPARATOR = " ";
2526

27+
/**
28+
* String to use in empty Object to separate start and end markers.
29+
* Default is single space, resulting in output of {@code { }}.
30+
*
31+
* @since 2.17
32+
*/
33+
public final static String DEFAULT_OBJECT_EMPTY_SEPARATOR = " ";
34+
35+
/**
36+
* String to use in empty Array to separate start and end markers.
37+
* Default is single space, resulting in output of {@code [ ]}.
38+
*
39+
* @since 2.17
40+
*/
41+
public final static String DEFAULT_ARRAY_EMPTY_SEPARATOR = " ";
42+
2643
/**
2744
* Define the spacing around elements like commas and colons.
2845
*
@@ -59,14 +76,20 @@ public String apply(char separator) {
5976
private final Spacing objectFieldValueSpacing;
6077
private final char objectEntrySeparator;
6178
private final Spacing objectEntrySpacing;
79+
private final String objectEmptySeparator;
6280
private final char arrayValueSeparator;
6381
private final Spacing arrayValueSpacing;
82+
private final String arrayEmptySeparator;
6483
private final String rootSeparator;
6584

6685
public static Separators createDefaultInstance() {
6786
return new Separators();
6887
}
6988

89+
/**
90+
* Constructor for creating an instance with default settings for all
91+
* separators.
92+
*/
7093
public Separators() {
7194
this(':', ',', ',');
7295
}
@@ -82,15 +105,18 @@ public Separators(
82105
) {
83106
this(DEFAULT_ROOT_VALUE_SEPARATOR,
84107
objectFieldValueSeparator, Spacing.BOTH,
85-
objectEntrySeparator, Spacing.NONE,
86-
arrayValueSeparator, Spacing.NONE);
108+
objectEntrySeparator, Spacing.NONE, DEFAULT_OBJECT_EMPTY_SEPARATOR,
109+
arrayValueSeparator, Spacing.NONE, DEFAULT_ARRAY_EMPTY_SEPARATOR);
87110
}
88111

89112
/**
90113
* Create an instance with the specified separator characters and spaces around those characters.
91114
*
92115
* @since 2.16
116+
*
117+
* @deprecated Since 2.17 use new canonical constructor
93118
*/
119+
@Deprecated // since 2.17
94120
public Separators(
95121
String rootSeparator,
96122
char objectFieldValueSeparator,
@@ -99,24 +125,48 @@ public Separators(
99125
Spacing objectEntrySpacing,
100126
char arrayValueSeparator,
101127
Spacing arrayValueSpacing
128+
) {
129+
this(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing,
130+
objectEntrySeparator, objectEntrySpacing, DEFAULT_OBJECT_EMPTY_SEPARATOR,
131+
arrayValueSeparator, arrayValueSpacing, DEFAULT_ARRAY_EMPTY_SEPARATOR);
132+
}
133+
134+
/**
135+
* Canonical constructor for creating an instance with the specified separator
136+
* characters and spaces around those characters.
137+
*
138+
* @since 2.17
139+
*/
140+
public Separators(
141+
String rootSeparator,
142+
char objectFieldValueSeparator,
143+
Spacing objectFieldValueSpacing,
144+
char objectEntrySeparator,
145+
Spacing objectEntrySpacing,
146+
String objectEmptySeparator,
147+
char arrayValueSeparator,
148+
Spacing arrayValueSpacing,
149+
String arrayEmptySeparator
102150
) {
103151
this.rootSeparator = rootSeparator;
104152
this.objectFieldValueSeparator = objectFieldValueSeparator;
105153
this.objectFieldValueSpacing = objectFieldValueSpacing;
106154
this.objectEntrySeparator = objectEntrySeparator;
107155
this.objectEntrySpacing = objectEntrySpacing;
156+
this.objectEmptySeparator = objectEmptySeparator;
108157
this.arrayValueSeparator = arrayValueSeparator;
109158
this.arrayValueSpacing = arrayValueSpacing;
159+
this.arrayEmptySeparator = arrayEmptySeparator;
110160
}
111161

112162
public Separators withRootSeparator(String sep) {
113163
return (rootSeparator.equals(sep)) ? this
114-
: new Separators(sep, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, arrayValueSeparator, arrayValueSpacing);
164+
: new Separators(sep, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, objectEmptySeparator, arrayValueSeparator, arrayValueSpacing, arrayEmptySeparator);
115165
}
116166

117167
public Separators withObjectFieldValueSeparator(char sep) {
118168
return (objectFieldValueSeparator == sep) ? this
119-
: new Separators(rootSeparator, sep, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, arrayValueSeparator, arrayValueSpacing);
169+
: new Separators(rootSeparator, sep, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, objectEmptySeparator, arrayValueSeparator, arrayValueSpacing, arrayEmptySeparator);
120170
}
121171

122172
/**
@@ -126,12 +176,12 @@ public Separators withObjectFieldValueSeparator(char sep) {
126176
*/
127177
public Separators withObjectFieldValueSpacing(Spacing spacing) {
128178
return (objectFieldValueSpacing == spacing) ? this
129-
: new Separators(rootSeparator, objectFieldValueSeparator, spacing, objectEntrySeparator, objectEntrySpacing, arrayValueSeparator, arrayValueSpacing);
179+
: new Separators(rootSeparator, objectFieldValueSeparator, spacing, objectEntrySeparator, objectEntrySpacing, objectEmptySeparator, arrayValueSeparator, arrayValueSpacing, arrayEmptySeparator);
130180
}
131181

132182
public Separators withObjectEntrySeparator(char sep) {
133183
return (objectEntrySeparator == sep) ? this
134-
: new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, sep, objectEntrySpacing, arrayValueSeparator, arrayValueSpacing);
184+
: new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, sep, objectEntrySpacing, objectEmptySeparator, arrayValueSeparator, arrayValueSpacing, arrayEmptySeparator);
135185
}
136186

137187
/**
@@ -141,12 +191,22 @@ public Separators withObjectEntrySeparator(char sep) {
141191
*/
142192
public Separators withObjectEntrySpacing(Spacing spacing) {
143193
return (objectEntrySpacing == spacing) ? this
144-
: new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, spacing, arrayValueSeparator, arrayValueSpacing);
194+
: new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, spacing, objectEmptySeparator, arrayValueSeparator, arrayValueSpacing, arrayEmptySeparator);
195+
}
196+
197+
/**
198+
* @return This instance (for call chaining)
199+
*
200+
* @since 2.17
201+
*/
202+
public Separators withObjectEmptySeparator(String sep) {
203+
return Objects.equals(arrayEmptySeparator, sep) ? this
204+
: new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, sep, arrayValueSeparator, arrayValueSpacing, arrayEmptySeparator);
145205
}
146206

147207
public Separators withArrayValueSeparator(char sep) {
148208
return (arrayValueSeparator == sep) ? this
149-
: new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, sep, arrayValueSpacing);
209+
: new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, objectEmptySeparator, sep, arrayValueSpacing, arrayEmptySeparator);
150210
}
151211

152212
/**
@@ -156,7 +216,17 @@ public Separators withArrayValueSeparator(char sep) {
156216
*/
157217
public Separators withArrayValueSpacing(Spacing spacing) {
158218
return (arrayValueSpacing == spacing) ? this
159-
: new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, arrayValueSeparator, spacing);
219+
: new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, objectEmptySeparator, arrayValueSeparator, spacing, arrayEmptySeparator);
220+
}
221+
222+
/**
223+
* @return This instance (for call chaining)
224+
*
225+
* @since 2.17
226+
*/
227+
public Separators withArrayEmptySeparator(String sep) {
228+
return Objects.equals(arrayEmptySeparator, sep) ? this
229+
: new Separators(rootSeparator, objectFieldValueSeparator, objectFieldValueSpacing, objectEntrySeparator, objectEntrySpacing, objectEmptySeparator, arrayValueSeparator, arrayValueSpacing, sep);
160230
}
161231

162232
/**
@@ -193,6 +263,15 @@ public char getObjectEntrySeparator() {
193263
public Spacing getObjectEntrySpacing() {
194264
return objectEntrySpacing;
195265
}
266+
267+
/**
268+
* @return String to use in empty Object
269+
*
270+
* @since 2.17
271+
*/
272+
public String getObjectEmptySeparator() {
273+
return objectEmptySeparator;
274+
}
196275

197276
public char getArrayValueSeparator() {
198277
return arrayValueSeparator;
@@ -206,4 +285,13 @@ public char getArrayValueSeparator() {
206285
public Spacing getArrayValueSpacing() {
207286
return arrayValueSpacing;
208287
}
288+
289+
/**
290+
* @return String to use in empty Array
291+
*
292+
* @since 2.17
293+
*/
294+
public String getArrayEmptySeparator() {
295+
return arrayEmptySeparator;
296+
}
209297
}

0 commit comments

Comments
 (0)