package com.fasterxml.jackson.databind.ser;

import com.fasterxml.jackson.annotation.JsonInclude;

import com.fasterxml.jackson.core.JsonGenerator;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.*;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
import com.fasterxml.jackson.databind.util.Annotations;

BeanPropertyWriter implementation used with JsonAppend to add "virtual" properties in addition to regular ones.
See Also:
Since:2.5
/** * {@link BeanPropertyWriter} implementation used with * {@link com.fasterxml.jackson.databind.annotation.JsonAppend} * to add "virtual" properties in addition to regular ones. * * @since 2.5 * * @see com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter */
public abstract class VirtualBeanPropertyWriter extends BeanPropertyWriter implements java.io.Serializable { private static final long serialVersionUID = 1L;
Constructor used by most sub-types.
/** * Constructor used by most sub-types. */
protected VirtualBeanPropertyWriter(BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType) { this(propDef, contextAnnotations, declaredType, null, null, null, propDef.findInclusion()); }
Constructor that may be used by sub-classes for constructing a "blue-print" instance; one that will only become (or create) actual usable instance when its withConfig method is called.
/** * Constructor that may be used by sub-classes for constructing a "blue-print" instance; * one that will only become (or create) actual usable instance when its * {@link #withConfig} method is called. */
protected VirtualBeanPropertyWriter() { super(); }
Pass-through constructor that may be used by sub-classes that want full control over implementation.
/** * Pass-through constructor that may be used by sub-classes that * want full control over implementation. */
protected VirtualBeanPropertyWriter(BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType, JsonSerializer<?> ser, TypeSerializer typeSer, JavaType serType, JsonInclude.Value inclusion, Class<?>[] includeInViews) { super(propDef, propDef.getPrimaryMember(), contextAnnotations, declaredType, ser, typeSer, serType, _suppressNulls(inclusion), _suppressableValue(inclusion), includeInViews); } @Deprecated // since 2.8 protected VirtualBeanPropertyWriter(BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType, JsonSerializer<?> ser, TypeSerializer typeSer, JavaType serType, JsonInclude.Value inclusion) { this(propDef, contextAnnotations, declaredType, ser, typeSer, serType, inclusion, null); } protected VirtualBeanPropertyWriter(VirtualBeanPropertyWriter base) { super(base); } protected VirtualBeanPropertyWriter(VirtualBeanPropertyWriter base, PropertyName name) { super(base, name); } protected static boolean _suppressNulls(JsonInclude.Value inclusion) { if (inclusion == null) { return false; } JsonInclude.Include incl = inclusion.getValueInclusion(); return (incl != JsonInclude.Include.ALWAYS) && (incl != JsonInclude.Include.USE_DEFAULTS); } protected static Object _suppressableValue(JsonInclude.Value inclusion) { if (inclusion == null) { return false; } JsonInclude.Include incl = inclusion.getValueInclusion(); if ((incl == JsonInclude.Include.ALWAYS) || (incl == JsonInclude.Include.NON_NULL) || (incl == JsonInclude.Include.USE_DEFAULTS)) { return null; } return MARKER_FOR_EMPTY; } /* /********************************************************** /* Standard accessor overrides /********************************************************** */ @Override public boolean isVirtual() { return true; } /* /********************************************************** /* Abstract methods for sub-classes to define /********************************************************** */
Method called to figure out the value to serialize. For simple sub-types (such as AttributePropertyWriter) this may be one of few methods to define, although more advanced implementations may choose to not even use this method (by overriding serializeAsField) and define a bogus implementation.
/** * Method called to figure out the value to serialize. For simple sub-types * (such as {@link com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter}) * this may be one of few methods to define, although more advanced implementations * may choose to not even use this method (by overriding {@link #serializeAsField}) * and define a bogus implementation. */
protected abstract Object value(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception;
Contextualization method called on a newly constructed virtual bean property. Usually a new intance needs to be created due to finality of some of configuration members; otherwise while recommended, creating a new instance is not strictly-speaking mandatory because calls are made in thread-safe manner, as part of initialization before use.
Params:
  • config – Currenct configuration; guaranteed to be SerializationConfig (just not typed since caller does not have dependency to serialization-specific types)
  • declaringClass – Class that contains this property writer
  • propDef – Nominal property definition to use
  • type – Declared type for the property
/** * Contextualization method called on a newly constructed virtual bean property. * Usually a new intance needs to be created due to finality of some of configuration * members; otherwise while recommended, creating a new instance is not strictly-speaking * mandatory because calls are made in thread-safe manner, as part of initialization * before use. * * @param config Currenct configuration; guaranteed to be {@link SerializationConfig} * (just not typed since caller does not have dependency to serialization-specific types) * @param declaringClass Class that contains this property writer * @param propDef Nominal property definition to use * @param type Declared type for the property */
public abstract VirtualBeanPropertyWriter withConfig(MapperConfig<?> config, AnnotatedClass declaringClass, BeanPropertyDefinition propDef, JavaType type); /* /********************************************************** /* PropertyWriter serialization method overrides /********************************************************** */ @Override public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { // NOTE: mostly copied from base class, but off-lined get() access final Object value = value(bean, gen, prov); if (value == null) { if (_nullSerializer != null) { gen.writeFieldName(_name); _nullSerializer.serialize(null, gen, prov); } return; } 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); } } if (_suppressableValue != null) { if (MARKER_FOR_EMPTY == _suppressableValue) { if (ser.isEmpty(prov, value)) { return; } } else if (_suppressableValue.equals(value)) { return; } } if (value == bean) { // simple check for direct cycles // three choices: exception; handled by call; or pass-through 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); } } // This one's fine as-is from base class //public void serializeAsOmittedField(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception @Override public void serializeAsElement(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception { // NOTE: mostly copied from base class, but off-lined get() access final Object value = value(bean, gen, prov); if (value == null) { if (_nullSerializer != null) { _nullSerializer.serialize(null, gen, prov); } else { gen.writeNull(); } return; } JsonSerializer<Object> ser = _serializer; if (ser == null) { Class<?> cls = value.getClass(); PropertySerializerMap map = _dynamicSerializers; ser = map.serializerFor(cls); if (ser == null) { ser = _findAndAddDynamic(map, cls, prov); } } if (_suppressableValue != null) { if (MARKER_FOR_EMPTY == _suppressableValue) { if (ser.isEmpty(prov, value)) { serializeAsPlaceholder(bean, gen, prov); return; } } else if (_suppressableValue.equals(value)) { serializeAsPlaceholder(bean, gen, prov); return; } } if (value == bean) { if (_handleSelfReference(bean, gen, prov, ser)) { return; } } if (_typeSerializer == null) { ser.serialize(value, gen, prov); } else { ser.serializeWithType(value, gen, prov, _typeSerializer); } } // This one's fine as-is from base class //public void serializeAsPlaceholder(Object bean, JsonGenerator jgen, SerializerProvider prov) }