FASTJSON 2 is a high-performance and easy-to-use Java JSON processing library with extreme performance that far exceeds other popular JSON libraries.
—
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.
Define custom deserialization logic for converting JSON data into Java objects with full control over the creation and population process.
/**
* Interface for custom object deserialization
* @param <T> Type of object to deserialize
*/
public interface ObjectReader<T> {
/**
* Create new instance of target type
* @return New object instance
*/
Object createInstance();
/**
* Read and deserialize object from JSON reader
* @param jsonReader JSON reader positioned at object start
* @return Deserialized object instance
*/
T readObject(JSONReader jsonReader);
/**
* Handle extra properties not defined in target class
* @param object Target object being populated
* @param fieldName Name of extra field
* @param fieldValue Value of extra field
*/
default void acceptExtra(Object object, String fieldName, Object fieldValue) {
// Default implementation ignores extra properties
}
/**
* Resolve automatic type detection
* @param typeName Type name from JSON
* @return Resolved class type
*/
default Class<?> autoType(String typeName) {
return null;
}
/**
* Get field readers for this object type
* @return Array of field readers
*/
default FieldReader<?>[] getFieldReaders() {
return new FieldReader[0];
}
}Define custom serialization logic for converting Java objects into JSON with control over field writing and formatting.
/**
* Interface for custom object serialization
* @param <T> Type of object to serialize
*/
public interface ObjectWriter<T> {
/**
* Write object to JSON writer
* @param jsonWriter JSON writer to write to
* @param object Object to serialize
* @param fieldName Field name if writing as property
* @param fieldType Field type information
* @param features Writer features
*/
void write(JSONWriter jsonWriter, Object object, Object fieldName,
Type fieldType, long features);
/**
* Write object in JSONB binary format
* @param jsonWriter JSONB writer
* @param object Object to serialize
* @param fieldName Field name if writing as property
* @param fieldType Field type information
* @param features Writer features
*/
default void writeJSONB(JSONWriter jsonWriter, Object object, Object fieldName,
Type fieldType, long features) {
write(jsonWriter, object, fieldName, fieldType, features);
}
/**
* Get field writers for this object type
* @return Array of field writers
*/
default FieldWriter<?>[] getFieldWriters() {
return new FieldWriter[0];
}
/**
* Check if this writer has filters applied
* @return true if filters are present
*/
default boolean hasFilter() {
return false;
}
}Handle individual field deserialization with type-specific optimizations and validation.
/**
* Field-level deserialization handler
* @param <T> Field type
*/
public abstract class FieldReader<T> {
/**
* Get field name
* @return Field name
*/
public String getFieldName();
/**
* Get field type
* @return Field type
*/
public Type getFieldType();
/**
* Get field class
* @return Field class
*/
public Class<T> getFieldClass();
/**
* Read field value from JSON reader
* @param jsonReader JSON reader
* @return Field value
*/
public abstract T readFieldValue(JSONReader jsonReader);
/**
* Accept and set field value on target object
* @param object Target object
* @param value Field value to set
*/
public abstract void accept(Object object, Object value);
/**
* Check if field is required
* @return true if field is required
*/
public boolean isRequired();
/**
* Get default value for field
* @return Default value or null
*/
public Object getDefaultValue();
}Handle individual field serialization with optimization and filtering capabilities.
/**
* Field-level serialization handler
* @param <T> Field type
*/
public abstract class FieldWriter<T> {
/**
* Get field name
* @return Field name
*/
public String getFieldName();
/**
* Get field type
* @return Field type
*/
public Type getFieldType();
/**
* Get field class
* @return Field class
*/
public Class<T> getFieldClass();
/**
* Write field to JSON writer
* @param jsonWriter JSON writer
* @param object Source object
*/
public abstract void writeValue(JSONWriter jsonWriter, Object object);
/**
* Get field value from object
* @param object Source object
* @return Field value
*/
public abstract Object getFieldValue(Object object);
/**
* Check if field should be written
* @param object Source object
* @return true if field should be included
*/
public boolean writeFieldName();
/**
* Get field annotation
* @param annotationClass Annotation class
* @return Annotation instance or null
*/
public <A extends Annotation> A getAnnotation(Class<A> annotationClass);
}Methods for registering custom readers/writers and creating instances.
/**
* Factory methods for creating readers and writers
*/
public class JSONFactory {
/**
* Get default ObjectReader for class
* @param objectType Target class
* @return ObjectReader instance
*/
public static <T> ObjectReader<T> getObjectReader(Class<T> objectType);
/**
* Get default ObjectWriter for class
* @param objectType Target class
* @return ObjectWriter instance
*/
public static <T> ObjectWriter<T> getObjectWriter(Class<T> objectType);
/**
* Create ObjectReader with features
* @param objectType Target class
* @param features Reader features
* @return ObjectReader instance
*/
public static <T> ObjectReader<T> createObjectReader(Class<T> objectType,
JSONReader.Feature... features);
}Usage Examples:
import com.alibaba.fastjson2.*;
import com.alibaba.fastjson2.reader.*;
import com.alibaba.fastjson2.writer.*;
// Custom ObjectReader for special deserialization logic
public class CustomUserReader implements ObjectReader<User> {
@Override
public Object createInstance() {
return new User();
}
@Override
public User readObject(JSONReader jsonReader) {
User user = new User();
jsonReader.nextIfObjectStart();
while (!jsonReader.nextIfObjectEnd()) {
String fieldName = jsonReader.readFieldName();
switch (fieldName) {
case "name":
user.setName(jsonReader.readString());
break;
case "age":
user.setAge(jsonReader.readInt32());
break;
case "email":
user.setEmail(jsonReader.readString());
break;
case "birthDate":
// Custom date parsing
String dateStr = jsonReader.readString();
user.setBirthDate(parseCustomDate(dateStr));
break;
default:
// Handle unknown fields
jsonReader.skipValue();
break;
}
}
return user;
}
@Override
public void acceptExtra(Object object, String fieldName, Object fieldValue) {
User user = (User) object;
// Store extra properties in a map
user.getExtraProperties().put(fieldName, fieldValue);
}
private Date parseCustomDate(String dateStr) {
// Custom date parsing logic
return new SimpleDateFormat("dd/MM/yyyy").parse(dateStr);
}
}
// Custom ObjectWriter for special serialization logic
public class CustomUserWriter implements ObjectWriter<User> {
@Override
public void write(JSONWriter jsonWriter, Object object, Object fieldName,
Type fieldType, long features) {
User user = (User) object;
jsonWriter.startObject();
// Write standard fields
jsonWriter.writeName("name");
jsonWriter.writeString(user.getName());
jsonWriter.writeName("age");
jsonWriter.writeInt32(user.getAge());
// Custom formatting for dates
if (user.getBirthDate() != null) {
jsonWriter.writeName("birthDate");
String formatted = new SimpleDateFormat("dd/MM/yyyy").format(user.getBirthDate());
jsonWriter.writeString(formatted);
}
// Include computed fields
jsonWriter.writeName("isAdult");
jsonWriter.writeBool(user.getAge() >= 18);
// Write extra properties
for (Map.Entry<String, Object> entry : user.getExtraProperties().entrySet()) {
jsonWriter.writeName(entry.getKey());
jsonWriter.writeAny(entry.getValue());
}
jsonWriter.endObject();
}
}
// Register custom readers and writers
JSON.register(User.class, new CustomUserReader());
JSON.register(User.class, new CustomUserWriter());
// Use custom logic
String json = "{\"name\":\"John\",\"age\":30,\"birthDate\":\"15/03/1994\",\"extra\":\"value\"}";
User user = JSON.parseObject(json, User.class); // Uses CustomUserReader
String serialized = JSON.toJSONString(user); // Uses CustomUserWriter
// Custom FieldReader for special field handling
public class EmailFieldReader extends FieldReader<String> {
@Override
public String getFieldName() {
return "email";
}
@Override
public Type getFieldType() {
return String.class;
}
@Override
public Class<String> getFieldClass() {
return String.class;
}
@Override
public String readFieldValue(JSONReader jsonReader) {
String email = jsonReader.readString();
// Validate email format
if (email != null && !email.contains("@")) {
throw new JSONException("Invalid email format: " + email);
}
return email;
}
@Override
public void accept(Object object, Object value) {
User user = (User) object;
user.setEmail((String) value);
}
@Override
public boolean isRequired() {
return true;
}
}
// Custom FieldWriter for special field formatting
public class TimestampFieldWriter extends FieldWriter<Date> {
@Override
public String getFieldName() {
return "timestamp";
}
@Override
public Type getFieldType() {
return Date.class;
}
@Override
public Class<Date> getFieldClass() {
return Date.class;
}
@Override
public void writeValue(JSONWriter jsonWriter, Object object) {
User user = (User) object;
Date timestamp = user.getTimestamp();
if (timestamp != null) {
// Write as Unix timestamp
jsonWriter.writeInt64(timestamp.getTime() / 1000);
} else {
jsonWriter.writeNull();
}
}
@Override
public Object getFieldValue(Object object) {
User user = (User) object;
return user.getTimestamp();
}
}
// Performance-optimized reader using annotation processing
@JSONCompiled
public class OptimizedUser {
private String name;
private int age;
private String email;
// FASTJSON2 generates optimized reader/writer at compile time
// for maximum performance
}
// Conditional reader based on JSON content
public class ConditionalReader implements ObjectReader<Shape> {
@Override
public Object createInstance() {
return null; // Will be determined by JSON content
}
@Override
public Shape readObject(JSONReader jsonReader) {
// Peek at JSON to determine actual type
JSONObject temp = jsonReader.readJSONObject();
if (temp.containsKey("radius")) {
return temp.to(Circle.class);
} else if (temp.containsKey("width") && temp.containsKey("height")) {
return temp.to(Rectangle.class);
} else {
throw new JSONException("Unknown shape type");
}
}
}
// Factory usage for creating readers with features
ObjectReader<User> userReader = JSONFactory.createObjectReader(
User.class,
JSONReader.Feature.SupportArrayToBean,
JSONReader.Feature.FieldBased
);
ObjectWriter<User> userWriter = JSONFactory.getObjectWriter(User.class);// Streaming reader for large datasets
public class StreamingUserReader implements ObjectReader<List<User>> {
@Override
public Object createInstance() {
return new ArrayList<User>();
}
@Override
public List<User> readObject(JSONReader jsonReader) {
List<User> users = new ArrayList<>();
jsonReader.nextIfArrayStart();
while (!jsonReader.nextIfArrayEnd()) {
User user = readSingleUser(jsonReader);
users.add(user);
// Process in batches to avoid memory issues
if (users.size() % 1000 == 0) {
processBatch(users);
users.clear();
}
}
if (!users.isEmpty()) {
processBatch(users);
}
return users;
}
private void processBatch(List<User> batch) {
// Process batch of users
System.out.println("Processed batch of " + batch.size() + " users");
}
}
// Encrypted field writer
public class EncryptedFieldWriter extends FieldWriter<String> {
private final String encryptionKey;
public EncryptedFieldWriter(String fieldName, String encryptionKey) {
this.encryptionKey = encryptionKey;
}
@Override
public void writeValue(JSONWriter jsonWriter, Object object) {
String value = (String) getFieldValue(object);
if (value != null) {
String encrypted = encrypt(value, encryptionKey);
jsonWriter.writeString(encrypted);
} else {
jsonWriter.writeNull();
}
}
private String encrypt(String value, String key) {
// Simple encryption example (use proper encryption in production)
return Base64.getEncoder().encodeToString(value.getBytes());
}
}Install with Tessl CLI
npx tessl i tessl/maven-com-alibaba-fastjson2--fastjson2