or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdformatting.mdinclusion-exclusion.mdindex.mdobject-creation.mdobject-identity.mdobject-structure.mdpolymorphic-types.mdproperty-control.md

formatting.mddocs/

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

```