0
# Reader/Writer Framework
1
2
Extensible framework for custom serialization and deserialization logic with ObjectReader and ObjectWriter interfaces. This system allows complete control over how objects are converted to and from JSON, enabling optimization and customization for specific use cases.
3
4
## Capabilities
5
6
### ObjectReader Interface
7
8
Define custom deserialization logic for converting JSON data into Java objects with full control over the creation and population process.
9
10
```java { .api }
11
/**
12
* Interface for custom object deserialization
13
* @param <T> Type of object to deserialize
14
*/
15
public interface ObjectReader<T> {
16
17
/**
18
* Create new instance of target type
19
* @return New object instance
20
*/
21
Object createInstance();
22
23
/**
24
* Read and deserialize object from JSON reader
25
* @param jsonReader JSON reader positioned at object start
26
* @return Deserialized object instance
27
*/
28
T readObject(JSONReader jsonReader);
29
30
/**
31
* Handle extra properties not defined in target class
32
* @param object Target object being populated
33
* @param fieldName Name of extra field
34
* @param fieldValue Value of extra field
35
*/
36
default void acceptExtra(Object object, String fieldName, Object fieldValue) {
37
// Default implementation ignores extra properties
38
}
39
40
/**
41
* Resolve automatic type detection
42
* @param typeName Type name from JSON
43
* @return Resolved class type
44
*/
45
default Class<?> autoType(String typeName) {
46
return null;
47
}
48
49
/**
50
* Get field readers for this object type
51
* @return Array of field readers
52
*/
53
default FieldReader<?>[] getFieldReaders() {
54
return new FieldReader[0];
55
}
56
}
57
```
58
59
### ObjectWriter Interface
60
61
Define custom serialization logic for converting Java objects into JSON with control over field writing and formatting.
62
63
```java { .api }
64
/**
65
* Interface for custom object serialization
66
* @param <T> Type of object to serialize
67
*/
68
public interface ObjectWriter<T> {
69
70
/**
71
* Write object to JSON writer
72
* @param jsonWriter JSON writer to write to
73
* @param object Object to serialize
74
* @param fieldName Field name if writing as property
75
* @param fieldType Field type information
76
* @param features Writer features
77
*/
78
void write(JSONWriter jsonWriter, Object object, Object fieldName,
79
Type fieldType, long features);
80
81
/**
82
* Write object in JSONB binary format
83
* @param jsonWriter JSONB writer
84
* @param object Object to serialize
85
* @param fieldName Field name if writing as property
86
* @param fieldType Field type information
87
* @param features Writer features
88
*/
89
default void writeJSONB(JSONWriter jsonWriter, Object object, Object fieldName,
90
Type fieldType, long features) {
91
write(jsonWriter, object, fieldName, fieldType, features);
92
}
93
94
/**
95
* Get field writers for this object type
96
* @return Array of field writers
97
*/
98
default FieldWriter<?>[] getFieldWriters() {
99
return new FieldWriter[0];
100
}
101
102
/**
103
* Check if this writer has filters applied
104
* @return true if filters are present
105
*/
106
default boolean hasFilter() {
107
return false;
108
}
109
}
110
```
111
112
### FieldReader Class
113
114
Handle individual field deserialization with type-specific optimizations and validation.
115
116
```java { .api }
117
/**
118
* Field-level deserialization handler
119
* @param <T> Field type
120
*/
121
public abstract class FieldReader<T> {
122
123
/**
124
* Get field name
125
* @return Field name
126
*/
127
public String getFieldName();
128
129
/**
130
* Get field type
131
* @return Field type
132
*/
133
public Type getFieldType();
134
135
/**
136
* Get field class
137
* @return Field class
138
*/
139
public Class<T> getFieldClass();
140
141
/**
142
* Read field value from JSON reader
143
* @param jsonReader JSON reader
144
* @return Field value
145
*/
146
public abstract T readFieldValue(JSONReader jsonReader);
147
148
/**
149
* Accept and set field value on target object
150
* @param object Target object
151
* @param value Field value to set
152
*/
153
public abstract void accept(Object object, Object value);
154
155
/**
156
* Check if field is required
157
* @return true if field is required
158
*/
159
public boolean isRequired();
160
161
/**
162
* Get default value for field
163
* @return Default value or null
164
*/
165
public Object getDefaultValue();
166
}
167
```
168
169
### FieldWriter Class
170
171
Handle individual field serialization with optimization and filtering capabilities.
172
173
```java { .api }
174
/**
175
* Field-level serialization handler
176
* @param <T> Field type
177
*/
178
public abstract class FieldWriter<T> {
179
180
/**
181
* Get field name
182
* @return Field name
183
*/
184
public String getFieldName();
185
186
/**
187
* Get field type
188
* @return Field type
189
*/
190
public Type getFieldType();
191
192
/**
193
* Get field class
194
* @return Field class
195
*/
196
public Class<T> getFieldClass();
197
198
/**
199
* Write field to JSON writer
200
* @param jsonWriter JSON writer
201
* @param object Source object
202
*/
203
public abstract void writeValue(JSONWriter jsonWriter, Object object);
204
205
/**
206
* Get field value from object
207
* @param object Source object
208
* @return Field value
209
*/
210
public abstract Object getFieldValue(Object object);
211
212
/**
213
* Check if field should be written
214
* @param object Source object
215
* @return true if field should be included
216
*/
217
public boolean writeFieldName();
218
219
/**
220
* Get field annotation
221
* @param annotationClass Annotation class
222
* @return Annotation instance or null
223
*/
224
public <A extends Annotation> A getAnnotation(Class<A> annotationClass);
225
}
226
```
227
228
### Registration and Factory
229
230
Methods for registering custom readers/writers and creating instances.
231
232
```java { .api }
233
/**
234
* Factory methods for creating readers and writers
235
*/
236
public class JSONFactory {
237
238
/**
239
* Get default ObjectReader for class
240
* @param objectType Target class
241
* @return ObjectReader instance
242
*/
243
public static <T> ObjectReader<T> getObjectReader(Class<T> objectType);
244
245
/**
246
* Get default ObjectWriter for class
247
* @param objectType Target class
248
* @return ObjectWriter instance
249
*/
250
public static <T> ObjectWriter<T> getObjectWriter(Class<T> objectType);
251
252
/**
253
* Create ObjectReader with features
254
* @param objectType Target class
255
* @param features Reader features
256
* @return ObjectReader instance
257
*/
258
public static <T> ObjectReader<T> createObjectReader(Class<T> objectType,
259
JSONReader.Feature... features);
260
}
261
```
262
263
**Usage Examples:**
264
265
```java
266
import com.alibaba.fastjson2.*;
267
import com.alibaba.fastjson2.reader.*;
268
import com.alibaba.fastjson2.writer.*;
269
270
// Custom ObjectReader for special deserialization logic
271
public class CustomUserReader implements ObjectReader<User> {
272
273
@Override
274
public Object createInstance() {
275
return new User();
276
}
277
278
@Override
279
public User readObject(JSONReader jsonReader) {
280
User user = new User();
281
282
jsonReader.nextIfObjectStart();
283
while (!jsonReader.nextIfObjectEnd()) {
284
String fieldName = jsonReader.readFieldName();
285
286
switch (fieldName) {
287
case "name":
288
user.setName(jsonReader.readString());
289
break;
290
case "age":
291
user.setAge(jsonReader.readInt32());
292
break;
293
case "email":
294
user.setEmail(jsonReader.readString());
295
break;
296
case "birthDate":
297
// Custom date parsing
298
String dateStr = jsonReader.readString();
299
user.setBirthDate(parseCustomDate(dateStr));
300
break;
301
default:
302
// Handle unknown fields
303
jsonReader.skipValue();
304
break;
305
}
306
}
307
308
return user;
309
}
310
311
@Override
312
public void acceptExtra(Object object, String fieldName, Object fieldValue) {
313
User user = (User) object;
314
// Store extra properties in a map
315
user.getExtraProperties().put(fieldName, fieldValue);
316
}
317
318
private Date parseCustomDate(String dateStr) {
319
// Custom date parsing logic
320
return new SimpleDateFormat("dd/MM/yyyy").parse(dateStr);
321
}
322
}
323
324
// Custom ObjectWriter for special serialization logic
325
public class CustomUserWriter implements ObjectWriter<User> {
326
327
@Override
328
public void write(JSONWriter jsonWriter, Object object, Object fieldName,
329
Type fieldType, long features) {
330
User user = (User) object;
331
332
jsonWriter.startObject();
333
334
// Write standard fields
335
jsonWriter.writeName("name");
336
jsonWriter.writeString(user.getName());
337
338
jsonWriter.writeName("age");
339
jsonWriter.writeInt32(user.getAge());
340
341
// Custom formatting for dates
342
if (user.getBirthDate() != null) {
343
jsonWriter.writeName("birthDate");
344
String formatted = new SimpleDateFormat("dd/MM/yyyy").format(user.getBirthDate());
345
jsonWriter.writeString(formatted);
346
}
347
348
// Include computed fields
349
jsonWriter.writeName("isAdult");
350
jsonWriter.writeBool(user.getAge() >= 18);
351
352
// Write extra properties
353
for (Map.Entry<String, Object> entry : user.getExtraProperties().entrySet()) {
354
jsonWriter.writeName(entry.getKey());
355
jsonWriter.writeAny(entry.getValue());
356
}
357
358
jsonWriter.endObject();
359
}
360
}
361
362
// Register custom readers and writers
363
JSON.register(User.class, new CustomUserReader());
364
JSON.register(User.class, new CustomUserWriter());
365
366
// Use custom logic
367
String json = "{\"name\":\"John\",\"age\":30,\"birthDate\":\"15/03/1994\",\"extra\":\"value\"}";
368
User user = JSON.parseObject(json, User.class); // Uses CustomUserReader
369
370
String serialized = JSON.toJSONString(user); // Uses CustomUserWriter
371
372
// Custom FieldReader for special field handling
373
public class EmailFieldReader extends FieldReader<String> {
374
375
@Override
376
public String getFieldName() {
377
return "email";
378
}
379
380
@Override
381
public Type getFieldType() {
382
return String.class;
383
}
384
385
@Override
386
public Class<String> getFieldClass() {
387
return String.class;
388
}
389
390
@Override
391
public String readFieldValue(JSONReader jsonReader) {
392
String email = jsonReader.readString();
393
// Validate email format
394
if (email != null && !email.contains("@")) {
395
throw new JSONException("Invalid email format: " + email);
396
}
397
return email;
398
}
399
400
@Override
401
public void accept(Object object, Object value) {
402
User user = (User) object;
403
user.setEmail((String) value);
404
}
405
406
@Override
407
public boolean isRequired() {
408
return true;
409
}
410
}
411
412
// Custom FieldWriter for special field formatting
413
public class TimestampFieldWriter extends FieldWriter<Date> {
414
415
@Override
416
public String getFieldName() {
417
return "timestamp";
418
}
419
420
@Override
421
public Type getFieldType() {
422
return Date.class;
423
}
424
425
@Override
426
public Class<Date> getFieldClass() {
427
return Date.class;
428
}
429
430
@Override
431
public void writeValue(JSONWriter jsonWriter, Object object) {
432
User user = (User) object;
433
Date timestamp = user.getTimestamp();
434
435
if (timestamp != null) {
436
// Write as Unix timestamp
437
jsonWriter.writeInt64(timestamp.getTime() / 1000);
438
} else {
439
jsonWriter.writeNull();
440
}
441
}
442
443
@Override
444
public Object getFieldValue(Object object) {
445
User user = (User) object;
446
return user.getTimestamp();
447
}
448
}
449
450
// Performance-optimized reader using annotation processing
451
@JSONCompiled
452
public class OptimizedUser {
453
private String name;
454
private int age;
455
private String email;
456
457
// FASTJSON2 generates optimized reader/writer at compile time
458
// for maximum performance
459
}
460
461
// Conditional reader based on JSON content
462
public class ConditionalReader implements ObjectReader<Shape> {
463
464
@Override
465
public Object createInstance() {
466
return null; // Will be determined by JSON content
467
}
468
469
@Override
470
public Shape readObject(JSONReader jsonReader) {
471
// Peek at JSON to determine actual type
472
JSONObject temp = jsonReader.readJSONObject();
473
474
if (temp.containsKey("radius")) {
475
return temp.to(Circle.class);
476
} else if (temp.containsKey("width") && temp.containsKey("height")) {
477
return temp.to(Rectangle.class);
478
} else {
479
throw new JSONException("Unknown shape type");
480
}
481
}
482
}
483
484
// Factory usage for creating readers with features
485
ObjectReader<User> userReader = JSONFactory.createObjectReader(
486
User.class,
487
JSONReader.Feature.SupportArrayToBean,
488
JSONReader.Feature.FieldBased
489
);
490
491
ObjectWriter<User> userWriter = JSONFactory.getObjectWriter(User.class);
492
```
493
494
### Advanced Reader/Writer Examples
495
496
```java
497
// Streaming reader for large datasets
498
public class StreamingUserReader implements ObjectReader<List<User>> {
499
500
@Override
501
public Object createInstance() {
502
return new ArrayList<User>();
503
}
504
505
@Override
506
public List<User> readObject(JSONReader jsonReader) {
507
List<User> users = new ArrayList<>();
508
509
jsonReader.nextIfArrayStart();
510
while (!jsonReader.nextIfArrayEnd()) {
511
User user = readSingleUser(jsonReader);
512
users.add(user);
513
514
// Process in batches to avoid memory issues
515
if (users.size() % 1000 == 0) {
516
processBatch(users);
517
users.clear();
518
}
519
}
520
521
if (!users.isEmpty()) {
522
processBatch(users);
523
}
524
525
return users;
526
}
527
528
private void processBatch(List<User> batch) {
529
// Process batch of users
530
System.out.println("Processed batch of " + batch.size() + " users");
531
}
532
}
533
534
// Encrypted field writer
535
public class EncryptedFieldWriter extends FieldWriter<String> {
536
private final String encryptionKey;
537
538
public EncryptedFieldWriter(String fieldName, String encryptionKey) {
539
this.encryptionKey = encryptionKey;
540
}
541
542
@Override
543
public void writeValue(JSONWriter jsonWriter, Object object) {
544
String value = (String) getFieldValue(object);
545
if (value != null) {
546
String encrypted = encrypt(value, encryptionKey);
547
jsonWriter.writeString(encrypted);
548
} else {
549
jsonWriter.writeNull();
550
}
551
}
552
553
private String encrypt(String value, String key) {
554
// Simple encryption example (use proper encryption in production)
555
return Base64.getEncoder().encodeToString(value.getBytes());
556
}
557
}
558
```