-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Is your feature request related to a problem? Please describe.
In BeanPropertyWriter
the get
method is final and a few of the serialization methods inline the call to get making it much more difficult to create sub-classes of BeanPropertyWriter
that attempt to optimize the get operation. An example of this can be seen in the Blackbird module which requires the entire serializeAsField
method to be overloaded (https://github.com/FasterXML/jackson-modules-base/blob/2.14/blackbird/src/main/java/com/fasterxml/jackson/module/blackbird/ser/ObjectPropertyWriter.java#L45) which then enforces additional constraints that the overload needs to handle complete serialization.
Describe the solution you'd like
I think it would be useful for sub-classes of BeanPropertyWriter
to be able to override get functionality and allow BeanPropertyWriter
to handle serialization based on its configuration (if serialization isn't also overridden). This would allow for further enhancements to the Blackbird module where it could become a simple optimized value getter using MethodHandle
based reflection and pass the retrieved back to the BeanPropertyWriter
. Overall, this would enable Blackbird to remove its restrictions on which types it is allowed to handle.
Usage example
BeanPropertyWriter.java
public void serializeAsField(Object bean, JsonGenerator gen,
SerializerProvider prov) throws Exception {
final Object value = getValue(bean);
// Null handling is bit different, check that first
if (value == null) {
if (_nullSerializer != null) {
gen.writeFieldName(_name);
_nullSerializer.serialize(null, gen, prov);
}
return;
}
// then find serializer to use
JsonSerializer<Object> ser = _serializer;
if (ser == null) {
Class<?> cls = value.getClass();
PropertySerializerMap m = _dynamicSerializers;
ser = m.serializerFor(cls);
if (ser == null) {
ser = _findAndAddDynamic(m, cls, prov);
}
}
// and then see if we must suppress certain values (default, empty)
if (_suppressableValue != null) {
if (MARKER_FOR_EMPTY == _suppressableValue) {
if (ser.isEmpty(prov, value)) {
return;
}
} else if (_suppressableValue.equals(value)) {
return;
}
}
// For non-nulls: simple check for direct cycles
if (value == bean) {
// four choices: exception; handled by call; pass-through or write null
if (_handleSelfReference(bean, gen, prov, ser)) {
return;
}
}
gen.writeFieldName(_name);
if (_typeSerializer == null) {
ser.serialize(value, gen, prov);
} else {
ser.serializeWithType(value, gen, prov, _typeSerializer);
}
}
// Basically the same as the existing get() as this changes the scope from "public final" to "protected"
protected Object getValue(Object bean) throws Exception {
return get(bean);
}
Blackbird Optimized Getters
@Override
protected Object getValue(Object bean) throws Exception {
// Insert optimized MethodHandle/Callsite retrieval here
}