package com.fasterxml.jackson.databind.ser; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.impl.BeanAsArraySerializer; import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter; import com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer; import com.fasterxml.jackson.databind.ser.impl.WritableObjectId; import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase; import com.fasterxml.jackson.databind.util.NameTransformer; /** * Serializer class that can serialize Java objects that map * to JSON Object output. Internally handling is mostly dealt with * by a sequence of {@link BeanPropertyWriter}s that will handle * access value to serialize and call appropriate serializers to * write out JSON. *<p> * Implementation note: we will post-process resulting serializer, * to figure out actual serializers for final types. This must be * done from {@link #resolve} method, and NOT from constructor; * otherwise we could end up with an infinite loop. */ public class BeanSerializer extends BeanSerializerBase { /* /********************************************************** /* Life-cycle: constructors /********************************************************** */ /** * @param builder Builder object that contains collected information * that may be needed for serializer * @param properties Property writers used for actual serialization */ public BeanSerializer(JavaType type, BeanSerializerBuilder builder, BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties) { super(type, builder, properties, filteredProperties); } /** * Alternate copy constructor that can be used to construct * standard {@link BeanSerializer} passing an instance of * "compatible enough" source serializer. */ protected BeanSerializer(BeanSerializerBase src) { super(src); } protected BeanSerializer(BeanSerializerBase src, ObjectIdWriter objectIdWriter) { super(src, objectIdWriter); } protected BeanSerializer(BeanSerializerBase src, String[] toIgnore) { super(src, toIgnore); } /* /********************************************************** /* Life-cycle: factory methods, fluent factories /********************************************************** */ /** * Method for constructing dummy bean serializer; one that * never outputs any properties */ public static BeanSerializer createDummy(JavaType forType) { return new BeanSerializer(forType, null, NO_PROPS, null); } @Override public JsonSerializer<Object> unwrappingSerializer(NameTransformer unwrapper) { return new UnwrappingBeanSerializer(this, unwrapper); } @Override public BeanSerializer withObjectIdWriter(ObjectIdWriter objectIdWriter) { return new BeanSerializer(this, objectIdWriter); } @Override protected BeanSerializer withIgnorals(String[] toIgnore) { return new BeanSerializer(this, toIgnore); } /** * Implementation has to check whether as-array serialization * is possible reliably; if (and only if) so, will construct * a {@link BeanAsArraySerializer}, otherwise will return this * serializer as is. */ @Override protected BeanSerializerBase asArraySerializer() { /* Can not: * * - have Object Id (may be allowed in future) * - have any getter * */ if ((_objectIdWriter == null) && (_anyGetterWriter == null) && (_propertyFilterId == null) ) { return new BeanAsArraySerializer(this); } // already is one, so: return this; } /* /********************************************************** /* JsonSerializer implementation that differs between impls /********************************************************** */ /** * Main serialization method that will delegate actual output to * configured * {@link BeanPropertyWriter} instances. */ @Override public final void serialize(Object bean, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { if (_objectIdWriter != null) { serializeWithObjectId(bean, jgen, provider); return; } jgen.writeStartObject(); if (_propertyFilterId != null) { serializeFieldsFiltered(bean, jgen, provider); } else { serializeFields(bean, jgen, provider); } jgen.writeEndObject(); } private final void serializeWithObjectId(Object bean, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { final ObjectIdWriter w = _objectIdWriter; WritableObjectId oid = provider.findObjectId(bean, w.generator); Object id = oid.id; if (id != null) { // have seen before; serialize just id oid.serializer.serialize(id, jgen, provider); return; } // if not, bit more work: oid.serializer = w.serializer; oid.id = id = oid.generator.generateId(bean); // possibly. Or maybe not: if (w.alwaysAsId) { oid.serializer.serialize(id, jgen, provider); return; } // If not, need to inject the id: jgen.writeStartObject(); SerializedString name = w.propertyName; if (name != null) { jgen.writeFieldName(name); w.serializer.serialize(id, jgen, provider); } if (_propertyFilterId != null) { serializeFieldsFiltered(bean, jgen, provider); } else { serializeFields(bean, jgen, provider); } jgen.writeEndObject(); } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return "BeanSerializer for "+handledType().getName(); } }