ObjectWriter.java
package com.alibaba.fastjson2.writer;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.*;
import com.alibaba.fastjson2.util.Fnv;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
/**
* ObjectWriter is responsible for serializing Java objects into JSON format.
* It provides a set of methods for writing objects to JSON, handling field mapping,
* and supporting various serialization features.
*
* <p>This interface supports various features including:
* <ul>
* <li>Object serialization to JSON and JSONB formats</li>
* <li>Field mapping and value extraction</li>
* <li>Array mapping serialization</li>
* <li>Type information writing</li>
* <li>Custom feature configuration</li>
* <li>Filter support for property filtering</li>
* </ul>
*
* <p>Example usage:
* <pre>
* // Get an ObjectWriter for a specific type
* ObjectWriter<User> writer = JSONFactory.getDefaultObjectWriterProvider().getObjectWriter(User.class);
*
* // Write to JSON string
* User user = new User(1, "John");
* String jsonString = writer.toJSONString(user);
*
* // Write to JSONWriter
* try (JSONWriter jsonWriter = JSONWriter.of()) {
* writer.write(jsonWriter, user);
* String result = jsonWriter.toString();
* }
* </pre>
*
* @param <T> the type of objects that this ObjectWriter can serialize
* @since 2.0.0
*/
public interface ObjectWriter<T> {
/**
* Gets the features enabled by this ObjectWriter.
*
* @return the enabled features as a bit mask
*/
default long getFeatures() {
return 0;
}
/**
* Gets the list of FieldWriters associated with this ObjectWriter.
*
* @return the list of FieldWriters, or an empty list if none are available
*/
default List<FieldWriter> getFieldWriters() {
return Collections.emptyList();
}
/**
* Gets the FieldWriter for the specified field hash code.
*
* @param hashCode the hash code of the field name
* @return the FieldWriter for the field, or null if not found
*/
default FieldWriter getFieldWriter(long hashCode) {
return null;
}
/**
* Gets the value of a field from the specified object.
*
* @param object the object from which to get the field value
* @param fieldName the name of the field to get
* @return the value of the field, or null if the field is not found
*/
default Object getFieldValue(Object object, String fieldName) {
FieldWriter fieldWriter = getFieldWriter(fieldName);
if (fieldWriter == null) {
return null;
}
return fieldWriter.getFieldValue(object);
}
/**
* Gets the FieldWriter for the specified field name.
*
* @param name the name of the field
* @return the FieldWriter for the field, or null if not found
*/
default FieldWriter getFieldWriter(String name) {
long nameHash = Fnv.hashCode64(name);
FieldWriter fieldWriter = getFieldWriter(nameHash);
if (fieldWriter == null) {
long nameHashLCase = Fnv.hashCode64LCase(name);
if (nameHashLCase != nameHash) {
fieldWriter = getFieldWriter(nameHashLCase);
}
}
return fieldWriter;
}
/**
* Writes type information to the JSON output. This is used for polymorphic serialization
* to include type information in the JSON output.
*
* @param jsonWriter the JSONWriter to which type information should be written
* @return true if type information was written, false otherwise
*/
default boolean writeTypeInfo(JSONWriter jsonWriter) {
return false;
}
/**
* Writes an object to the JSONWriter in JSONB format.
*
* @param jsonWriter the JSONWriter to which the object should be written
* @param object the object to write
* @param fieldName the name of the field being written
* @param fieldType the type of the field being written
* @param features the features to use for writing
*/
default void writeJSONB(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
write(jsonWriter, object, fieldName, fieldType, features);
}
/**
* Writes an object to the JSONWriter in array mapping JSONB format.
*
* @param jsonWriter the JSONWriter to which the object should be written
* @param object the object to write
*/
default void writeArrayMappingJSONB(JSONWriter jsonWriter, Object object) {
writeArrayMappingJSONB(jsonWriter, object, null, null, 0);
}
/**
* Writes an object to the JSONWriter in array mapping JSONB format with additional parameters.
*
* @param jsonWriter the JSONWriter to which the object should be written
* @param object the object to write
* @param fieldName the name of the field being written
* @param fieldType the type of the field being written
* @param features the features to use for writing
*/
default void writeArrayMappingJSONB(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
List<FieldWriter> fieldWriters = getFieldWriters();
int size = fieldWriters.size();
jsonWriter.startArray(size);
for (int i = 0; i < size; ++i) {
FieldWriter fieldWriter = fieldWriters.get(i);
fieldWriter.writeValue(jsonWriter, object);
}
}
/**
* Writes an object to the JSONWriter in array mapping format.
*
* @param jsonWriter the JSONWriter to which the object should be written
* @param object the object to write
* @param fieldName the name of the field being written
* @param fieldType the type of the field being written
* @param features the features to use for writing
*/
default void writeArrayMapping(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
if (jsonWriter.jsonb) {
writeArrayMappingJSONB(jsonWriter, object, fieldName, fieldType, features);
return;
}
List<FieldWriter> fieldWriters = getFieldWriters();
jsonWriter.startArray();
boolean hasFilter = hasFilter(jsonWriter);
if (!hasFilter) {
for (int i = 0, size = fieldWriters.size(); i < size; ++i) {
if (i != 0) {
jsonWriter.writeComma();
}
FieldWriter fieldWriter = fieldWriters.get(i);
fieldWriter.writeValue(jsonWriter, object);
}
} else {
JSONWriter.Context ctx = jsonWriter.context;
PropertyPreFilter propertyPreFilter = ctx.getPropertyPreFilter();
ValueFilter valueFilter = ctx.getValueFilter();
PropertyFilter propertyFilter = ctx.getPropertyFilter();
for (int i = 0, size = fieldWriters.size(); i < size; ++i) {
if (i != 0) {
jsonWriter.writeComma();
}
FieldWriter fieldWriter = fieldWriters.get(i);
if (propertyPreFilter != null && !propertyPreFilter.process(jsonWriter, object, fieldWriter.fieldName)) {
jsonWriter.writeNull();
continue;
}
Object fieldValue = fieldWriter.getFieldValue(object);
if (propertyFilter != null && !propertyFilter.apply(object, fieldWriter.fieldName, fieldValue)) {
jsonWriter.writeNull();
continue;
}
if (valueFilter != null) {
Object processValue = valueFilter.apply(object, fieldWriter.fieldName, fieldValue);
if (processValue == null) {
jsonWriter.writeNull();
continue;
}
ObjectWriter processValueWriter = fieldWriter.getObjectWriter(jsonWriter, processValue.getClass());
processValueWriter.write(jsonWriter, fieldValue);
} else {
if (fieldValue == null) {
jsonWriter.writeNull();
continue;
}
ObjectWriter fieldValueWriter = fieldWriter.getObjectWriter(jsonWriter, fieldValue.getClass());
fieldValueWriter.write(jsonWriter, fieldValue);
}
}
}
jsonWriter.endArray();
}
/**
* Checks if the JSONWriter has any filters enabled that would affect serialization.
*
* @param jsonWriter the JSONWriter to check
* @return true if filters are enabled, false otherwise
*/
default boolean hasFilter(JSONWriter jsonWriter) {
return jsonWriter.hasFilter(JSONWriter.Feature.IgnoreNonFieldGetter.mask);
}
/**
* Writes an object to the JSONWriter using default parameters.
*
* @param jsonWriter the JSONWriter to which the object should be written
* @param object the object to write
*/
default void write(JSONWriter jsonWriter, Object object) {
write(jsonWriter, object, null, null, 0);
}
/**
* Converts an object to its JSON string representation using the specified features.
*
* @param object the object to convert to JSON
* @param features the JSON writer features to use
* @return the JSON string representation of the object
*/
default String toJSONString(T object, JSONWriter.Feature... features) {
try (JSONWriter jsonWriter = JSONWriter.of(features)) {
write(jsonWriter, object, null, null, 0);
return jsonWriter.toString();
}
}
/**
* Writes an object to the JSONWriter with the given field name, field type, and features.
*
* @param jsonWriter the JSONWriter to which the object should be written
* @param object the object to write
* @param fieldName the name of the field being written
* @param fieldType the type of the field being written
* @param features the features to use for writing
*/
void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features);
/**
* Writes an object to the JSONWriter with filter support using default parameters.
*
* @param jsonWriter the JSONWriter to which the object should be written
* @param object the object to write
*/
default void writeWithFilter(JSONWriter jsonWriter, Object object) {
writeWithFilter(jsonWriter, object, null, null, 0);
}
/**
* Writes an object to the JSONWriter with filter support.
*
* @param jsonWriter the JSONWriter to which the object should be written
* @param object the object to write
* @param fieldName the name of the field being written
* @param fieldType the type of the field being written
* @param features the features to use for writing
* @throws UnsupportedOperationException if the method is not implemented
*/
default void writeWithFilter(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
throw new UnsupportedOperationException();
}
/**
* Sets the property filter for this ObjectWriter.
*
* @param propertyFilter the property filter to set
*/
default void setPropertyFilter(PropertyFilter propertyFilter) {
}
/**
* Sets the value filter for this ObjectWriter.
*
* @param valueFilter the value filter to set
*/
default void setValueFilter(ValueFilter valueFilter) {
}
/**
* Sets the name filter for this ObjectWriter.
*
* @param nameFilter the name filter to set
*/
default void setNameFilter(NameFilter nameFilter) {
}
/**
* Sets the property pre-filter for this ObjectWriter.
*
* @param propertyPreFilter the property pre-filter to set
*/
default void setPropertyPreFilter(PropertyPreFilter propertyPreFilter) {
}
/**
* Sets a filter for this ObjectWriter. The filter type is determined at runtime
* and the appropriate setter method is called.
*
* @param filter the filter to set
*/
default void setFilter(Filter filter) {
if (filter instanceof PropertyFilter) {
setPropertyFilter((PropertyFilter) filter);
}
if (filter instanceof ValueFilter) {
setValueFilter((ValueFilter) filter);
}
if (filter instanceof NameFilter) {
setNameFilter((NameFilter) filter);
}
if (filter instanceof PropertyPreFilter) {
setPropertyPreFilter((PropertyPreFilter) filter);
}
}
}