or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdannotations.mdcore-operations.mddata-structures.mdindex.mdreader-writer.md

reader-writer.mddocs/

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

```