0
# Formatting and Serialization Control
1
2
Control serialization format for dates, numbers, and other values with comprehensive formatting options.
3
4
## Capabilities
5
6
### JsonFormat
7
8
Configure serialization format for values including dates, numbers, and collections.
9
10
```java { .api }
11
/**
12
* Configure serialization format for values
13
* @param pattern Format pattern (e.g., date pattern, number pattern)
14
* @param shape Serialization shape/structure
15
* @param locale Locale for formatting (default: "##default")
16
* @param timezone Timezone for date formatting (default: "##default")
17
* @param lenient Whether to use lenient parsing
18
* @param with Format features to enable
19
* @param without Format features to disable
20
*/
21
@JsonFormat(String pattern = "",
22
JsonFormat.Shape shape = JsonFormat.Shape.ANY,
23
String locale = JsonFormat.DEFAULT_LOCALE,
24
String timezone = JsonFormat.DEFAULT_TIMEZONE,
25
OptBoolean lenient = OptBoolean.DEFAULT,
26
JsonFormat.Feature[] with = {},
27
JsonFormat.Feature[] without = {})
28
public @interface JsonFormat {
29
30
enum Shape {
31
/** Use natural/default shape for the type */
32
ANY,
33
34
/** Use natural shape (object for objects, array for arrays) */
35
NATURAL,
36
37
/** Force scalar representation */
38
SCALAR,
39
40
/** Force array representation */
41
ARRAY,
42
43
/** Force object representation */
44
OBJECT,
45
46
/** Force numeric representation */
47
NUMBER,
48
49
/** Force floating-point number */
50
NUMBER_FLOAT,
51
52
/** Force integer number */
53
NUMBER_INT,
54
55
/** Force string representation */
56
STRING,
57
58
/** Force boolean representation */
59
BOOLEAN,
60
61
/** Force binary representation */
62
BINARY;
63
64
public boolean isNumeric();
65
public boolean isStructured();
66
}
67
68
enum Feature {
69
/** Accept single value as single-element array */
70
ACCEPT_SINGLE_VALUE_AS_ARRAY,
71
72
/** Accept case-insensitive property names */
73
ACCEPT_CASE_INSENSITIVE_PROPERTIES,
74
75
/** Read unknown enum values as null */
76
READ_UNKNOWN_ENUM_VALUES_AS_NULL,
77
78
/** Read unknown enum values using @JsonEnumDefaultValue */
79
READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE,
80
81
/** Read date timestamps as nanoseconds instead of milliseconds */
82
READ_DATE_TIMESTAMPS_AS_NANOSECONDS,
83
84
/** Accept case-insensitive enum values */
85
ACCEPT_CASE_INSENSITIVE_VALUES,
86
87
/** Write date timestamps as nanoseconds */
88
WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS,
89
90
/** Write dates with zone ID information */
91
WRITE_DATES_WITH_ZONE_ID,
92
93
/** Write single-element arrays without array wrapper */
94
WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED,
95
96
/** Write Map entries in sorted order */
97
WRITE_SORTED_MAP_ENTRIES,
98
99
/** Adjust dates to context timezone */
100
ADJUST_DATES_TO_CONTEXT_TIME_ZONE
101
}
102
103
/** Default locale marker */
104
String DEFAULT_LOCALE = "##default";
105
106
/** Default timezone marker */
107
String DEFAULT_TIMEZONE = "##default";
108
}
109
```
110
111
**Usage Examples:**
112
113
```java
114
public class Event {
115
private String name;
116
117
// Date formatting with pattern
118
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
119
private LocalDateTime eventTime;
120
121
// Date as timestamp (milliseconds)
122
@JsonFormat(shape = JsonFormat.Shape.NUMBER)
123
private LocalDateTime createdAt;
124
125
// Date as string with timezone
126
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC")
127
private ZonedDateTime scheduledTime;
128
129
// Number formatting
130
@JsonFormat(pattern = "#,##0.00")
131
private BigDecimal price;
132
133
// Array as single value when only one element
134
@JsonFormat(with = JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)
135
private List<String> tags;
136
}
137
138
// Results:
139
// "eventTime": "2024-01-15 14:30:00"
140
// "createdAt": 1705328200000
141
// "scheduledTime": "2024-01-15T14:30:00.000Z"
142
// "price": "1,234.56"
143
// "tags": "single-tag" (instead of ["single-tag"])
144
```
145
146
### Enum Formatting
147
148
```java
149
public enum Priority {
150
@JsonFormat(shape = JsonFormat.Shape.NUMBER)
151
LOW(1),
152
153
@JsonFormat(shape = JsonFormat.Shape.NUMBER)
154
MEDIUM(2),
155
156
@JsonFormat(shape = JsonFormat.Shape.NUMBER)
157
HIGH(3);
158
159
private final int value;
160
161
Priority(int value) {
162
this.value = value;
163
}
164
165
@JsonValue
166
public int getValue() {
167
return value;
168
}
169
}
170
171
// Serializes as: 1, 2, 3 instead of "LOW", "MEDIUM", "HIGH"
172
```
173
174
### Collection and Map Formatting
175
176
```java
177
public class DataContainer {
178
// Sort map entries during serialization
179
@JsonFormat(with = JsonFormat.Feature.WRITE_SORTED_MAP_ENTRIES)
180
private Map<String, Object> properties;
181
182
// Accept single value as array
183
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
184
private List<String> items;
185
186
// Custom array formatting
187
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
188
private String[] coordinates; // Force object representation instead of array
189
}
190
191
// properties will be serialized with keys in alphabetical order
192
// items can deserialize both ["value"] and "value" as single-element array
193
// coordinates might serialize as {"0": "x", "1": "y"} instead of ["x", "y"]
194
```
195
196
## Advanced Formatting Patterns
197
198
### Locale-Specific Formatting
199
200
```java
201
public class LocalizedData {
202
@JsonFormat(pattern = "dd/MM/yyyy", locale = "en_GB")
203
private LocalDate ukDate;
204
205
@JsonFormat(pattern = "MM/dd/yyyy", locale = "en_US")
206
private LocalDate usDate;
207
208
@JsonFormat(pattern = "#,##0.00", locale = "de_DE")
209
private BigDecimal germanNumber; // Uses comma as decimal separator
210
211
@JsonFormat(pattern = "#,##0.00", locale = "en_US")
212
private BigDecimal usNumber; // Uses period as decimal separator
213
}
214
```
215
216
### Timezone Handling
217
218
```java
219
public class TimeZoneExample {
220
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC")
221
private LocalDateTime utcTime;
222
223
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "America/New_York")
224
private LocalDateTime nyTime;
225
226
@JsonFormat(with = JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
227
private ZonedDateTime contextTime; // Adjusts to ObjectMapper's timezone
228
229
@JsonFormat(with = JsonFormat.Feature.WRITE_DATES_WITH_ZONE_ID)
230
private ZonedDateTime zoneDateTime; // Includes zone ID in output
231
}
232
```
233
234
### Custom Shape Formatting
235
236
```java
237
public class ShapeExamples {
238
// Force string representation of number
239
@JsonFormat(shape = JsonFormat.Shape.STRING)
240
private Long bigId; // "123456789012345" instead of 123456789012345
241
242
// Force array representation of single value
243
@JsonFormat(shape = JsonFormat.Shape.ARRAY)
244
private String singleValue; // ["value"] instead of "value"
245
246
// Force object representation of primitive
247
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
248
private boolean flag; // {"value": true} instead of true
249
}
250
```
251
252
### Feature Combinations
253
254
```java
255
public class FeatureCombinations {
256
@JsonFormat(
257
pattern = "yyyy-MM-dd",
258
with = {
259
JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE,
260
JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES
261
},
262
without = {
263
JsonFormat.Feature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS
264
}
265
)
266
private LocalDate configuredDate;
267
268
@JsonFormat(
269
with = {
270
JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED,
271
JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY
272
}
273
)
274
private List<String> flexibleArray;
275
}
276
```
277
278
### JsonEnumDefaultValue
279
280
Mark enum field as default value for unknown enum values during deserialization.
281
282
```java { .api }
283
/**
284
* Mark enum value as default for unknown enum values
285
* Only effective when READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE is enabled
286
*/
287
@JsonEnumDefaultValue
288
public @interface JsonEnumDefaultValue;
289
```
290
291
**Usage Examples:**
292
293
```java
294
public enum Status {
295
ACTIVE,
296
INACTIVE,
297
PENDING,
298
299
@JsonEnumDefaultValue
300
UNKNOWN; // Used when deserializing unrecognized values
301
}
302
303
public class Order {
304
private Status status;
305
306
// When JSON contains {"status": "CANCELLED"} (unknown value)
307
// It will deserialize as Status.UNKNOWN if feature is enabled
308
}
309
```
310
311
### JsonFormat.Value and JsonFormat.Features
312
313
Configuration classes for programmatic format control.
314
315
```java { .api }
316
/**
317
* Value class for JsonFormat configuration
318
*/
319
public static class JsonFormat.Value implements JacksonAnnotationValue<JsonFormat> {
320
public static final JsonFormat.Value EMPTY;
321
322
public static JsonFormat.Value forPattern(String pattern);
323
public static JsonFormat.Value forShape(JsonFormat.Shape shape);
324
public static JsonFormat.Value forLeniency(Boolean lenient);
325
326
public String getPattern();
327
public JsonFormat.Shape getShape();
328
public Locale getLocale();
329
public TimeZone getTimeZone();
330
public Boolean getLenient();
331
public JsonFormat.Features getFeatures();
332
333
public JsonFormat.Value withPattern(String pattern);
334
public JsonFormat.Value withShape(JsonFormat.Shape shape);
335
public JsonFormat.Value withLocale(Locale locale);
336
public JsonFormat.Value withTimeZone(TimeZone tz);
337
public JsonFormat.Value withLenient(Boolean lenient);
338
public JsonFormat.Value withFeature(JsonFormat.Feature feature);
339
public JsonFormat.Value withoutFeature(JsonFormat.Feature feature);
340
}
341
342
/**
343
* Helper class for managing format features
344
*/
345
public static class JsonFormat.Features {
346
public static final JsonFormat.Features EMPTY;
347
348
public static JsonFormat.Features construct(JsonFormat.Feature[] enabled,
349
JsonFormat.Feature[] disabled);
350
351
public JsonFormat.Features with(JsonFormat.Feature... features);
352
public JsonFormat.Features without(JsonFormat.Feature... features);
353
public boolean get(JsonFormat.Feature feature);
354
}
355
```
356
357
### Conditional Formatting
358
359
```java
360
public class ConditionalFormatting {
361
// Different format based on value
362
@JsonFormat(shape = JsonFormat.Shape.STRING)
363
private Long getId() {
364
// Custom getter that formats differently based on conditions
365
return id != null && id > 1000000L ? id : null;
366
}
367
368
// Lenient parsing for user input
369
@JsonFormat(lenient = OptBoolean.TRUE)
370
private LocalDate userInputDate; // More forgiving date parsing
371
372
// Strict formatting for API output
373
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", lenient = OptBoolean.FALSE)
374
private LocalDateTime apiTimestamp;
375
}
376
```