Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.fasterxml.jackson.databind.ser.std;
  
  import java.util.*;
  
 
Base class both for the standard bean serializer, and couple of variants that only differ in small details. Can be used for custom bean serializers as well, although that is not the primary design goal.
 
 public abstract class BeanSerializerBase
     extends StdSerializer<Object>
 {
     final protected static BeanPropertyWriter[] NO_PROPS = new BeanPropertyWriter[0];
 
     /*
     /**********************************************************
     /* Configuration
     /**********************************************************
      */

    
Writers used for outputting actual property values
 
     final protected BeanPropertyWriter[] _props;

    
Optional filters used to suppress output of properties that are only to be included in certain views
 
     final protected BeanPropertyWriter[] _filteredProps;

    
Handler for com.fasterxml.jackson.annotation.JsonAnyGetter annotated properties
 
     final protected AnyGetterWriter _anyGetterWriter;
    
    
Id of the bean property filter to use, if any; null if none.
 
     final protected Object _propertyFilterId;

    
If using custom type ids (usually via getter, or field), this is the reference to that member.
 
     final protected AnnotatedMember _typeId;
    
    
If this POJO can be alternatively serialized using just an object id to denote a reference to previously serialized object, this Object will handle details.
 
     final protected ObjectIdWriter _objectIdWriter;

    
Requested shape from bean class annotations.
 
     final protected JsonFormat.Shape _serializationShape;
     
     /*
     /**********************************************************
     /* Life-cycle: constructors
     /**********************************************************
      */

    
Constructor used by com.fasterxml.jackson.databind.ser.BeanSerializerBuilder to create an instance

Parameters:
type Nominal type of values handled by this serializer
builder Builder for accessing other collected information
    protected BeanSerializerBase(JavaType typeBeanSerializerBuilder builder,
            BeanPropertyWriter[] propertiesBeanPropertyWriter[] filteredProperties)
    {
        super(type);
         = properties;
         = filteredProperties;
        if (builder == null) { // mostly for testing
             = null;
             = null;
             = null;
             = null;
             = null;
        } else {
             = builder.getTypeId();
             = builder.getAnyGetter();
             = builder.getFilterId();
             = builder.getObjectIdWriter();
            JsonFormat.Value format = builder.getBeanDescription().findExpectedFormat(null);
             = (format == null) ? null : format.getShape();
        }
    }
            BeanPropertyWriter[] propertiesBeanPropertyWriter[] filteredProperties)
    {
        super(src._handledType);
         = properties;
         = filteredProperties;
         = src._typeId;
         = src._anyGetterWriter;
         = src._objectIdWriter;
         = src._propertyFilterId;
         = src._serializationShape;
    }
    protected BeanSerializerBase(BeanSerializerBase srcObjectIdWriter objectIdWriter)
    {
        super(src._handledType);
         = src._props;
         = src._filteredProps;
        
         = src._typeId;
         = src._anyGetterWriter;
         = objectIdWriter;
         = src._propertyFilterId;
         = src._serializationShape;
    }
    protected BeanSerializerBase(BeanSerializerBase srcString[] toIgnore)
    {
        super(src._handledType);
        // Bit clumsy, but has to do:
        HashSet<StringignoredSet = ArrayBuilders.arrayToSet(toIgnore);
        final BeanPropertyWriter[] propsIn = src._props;
        final BeanPropertyWriter[] fpropsIn = src._filteredProps;
        final int len = propsIn.length;
        ArrayList<BeanPropertyWriterpropsOut = new ArrayList<BeanPropertyWriter>(len);
        ArrayList<BeanPropertyWriterfpropsOut = (fpropsIn == null) ? null : new ArrayList<BeanPropertyWriter>(len);
        for (int i = 0; i < len; ++i) {
            BeanPropertyWriter bpw = propsIn[i];
            // should be ignored?
            if (ignoredSet.contains(bpw.getName())) {
                continue;
            }
            propsOut.add(bpw);
            if (fpropsIn != null) {
                fpropsOut.add(fpropsIn[i]);
            }
        }
         = propsOut.toArray(new BeanPropertyWriter[propsOut.size()]);
         = (fpropsOut == null) ? null : fpropsOut.toArray(new BeanPropertyWriter[fpropsOut.size()]);
        
         = src._typeId;
         = src._anyGetterWriter;
         = src._objectIdWriter;
         = src._propertyFilterId;
         = src._serializationShape;
    }
    
    
Fluent factory used for creating a new instance with different com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter.

Since:
2.0
    public abstract BeanSerializerBase withObjectIdWriter(ObjectIdWriter objectIdWriter);

    
Fluent factory used for creating a new instance with additional set of properties to ignore (from properties this instance otherwise has)

Since:
2.0
    protected abstract BeanSerializerBase withIgnorals(String[] toIgnore);

    
Fluent factory for creating a variant that output POJO as a JSON Array. Implementations may ignore this request if output as array is not possible (either at all, or reliably).

Since:
2.1
    protected abstract BeanSerializerBase asArraySerializer();
    
    
Copy-constructor that is useful for sub-classes that just want to copy all super-class properties without modifications.
    protected BeanSerializerBase(BeanSerializerBase src) {
        this(srcsrc._propssrc._filteredProps);
    }

    
Copy-constructor that will also rename properties with given prefix (if it's non-empty)
    protected BeanSerializerBase(BeanSerializerBase srcNameTransformer unwrapper) {
        this(srcrename(src._propsunwrapper), rename(src._filteredPropsunwrapper));
    }
    
    private final static BeanPropertyWriter[] rename(BeanPropertyWriter[] props,
            NameTransformer transformer)
    {
        if (props == null || props.length == 0 || transformer == null || transformer == .) {
            return props;
        }
        final int len = props.length;
        BeanPropertyWriter[] result = new BeanPropertyWriter[len];
        for (int i = 0; i < len; ++i) {
            BeanPropertyWriter bpw = props[i];
            if (bpw != null) {
                result[i] = bpw.rename(transformer);
            }
        }
        return result;
    }
    /*
    /**********************************************************
    /* Post-constriction processing: resolvable, contextual
    /**********************************************************
     */

    
We need to implement com.fasterxml.jackson.databind.ser.ResolvableSerializer to be able to properly handle cyclic type references.
//  @Override
    public void resolve(SerializerProvider provider)
        throws JsonMappingException
    {
        int filteredCount = ( == null) ? 0 : .;
        for (int i = 0, len = .i < len; ++i) {
            BeanPropertyWriter prop = [i];
            // let's start with null serializer resolution actually
            if (!prop.willSuppressNulls() && !prop.hasNullSerializer()) {
                JsonSerializer<ObjectnullSer = provider.findNullValueSerializer(prop);
                if (nullSer != null) {
                    prop.assignNullSerializer(nullSer);
                    // also: remember to replace filtered property too? (see [JACKSON-364])
                    if (i < filteredCount) {
                        BeanPropertyWriter w2 = [i];
                        if (w2 != null) {
                            w2.assignNullSerializer(nullSer);
                        }
                    }
                }
            }
            
            if (prop.hasSerializer()) {
                continue;
            }
            // Was the serialization type hard-coded? If so, use it
            JavaType type = prop.getSerializationType();
            
            /* It not, we can use declared return type if and only if
             * declared type is final -- if not, we don't really know
             * the actual type until we get the instance.
             */
            if (type == null) {
                type = provider.constructType(prop.getGenericPropertyType());
                if (!type.isFinal()) {
                    /* 18-Feb-2010, tatus: But even if it is non-final, we may
                     *   need to retain some of type information so that we can
                     *   accurately handle contained types
                     */
                    if (type.isContainerType() || type.containedTypeCount() > 0) {
                        prop.setNonTrivialBaseType(type);
                    }
                    continue;
                }
            }
            
            JsonSerializer<Objectser = provider.findValueSerializer(typeprop);
            /* 04-Feb-2010, tatu: We may have stashed type serializer for content types
             *   too, earlier; if so, it's time to connect the dots here:
             */
            if (type.isContainerType()) {
                TypeSerializer typeSer = type.getContentType().getTypeHandler();
                if (typeSer != null) {
                    // for now, can do this only for standard containers...
                    if (ser instanceof ContainerSerializer<?>) {
                        // ugly casts... but necessary
                        @SuppressWarnings("unchecked")
                        JsonSerializer<Objectser2 = (JsonSerializer<Object>)((ContainerSerializer<?>) ser).withValueTypeSerializer(typeSer);
                        ser = ser2;
                    }
                }
            }
            prop.assignSerializer(ser);
            // and maybe replace filtered property too? (see [JACKSON-364])
            if (i < filteredCount) {
                BeanPropertyWriter w2 = [i];
                if (w2 != null) {
                    w2.assignSerializer(ser);
                }
            }
        }
        // also, any-getter may need to be resolved
        if ( != null) {
            .resolve(provider);
        }
    }
//  @Override
            BeanProperty property)
        throws JsonMappingException
    {
        ObjectIdWriter oiw = ;
        String[] ignorals = null;
        final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
        final AnnotatedMember accessor = (property == null || intr == null)
                ? null : property.getMember();
        
        // First: may have an override for Object Id:
        if (accessor != null) {
            ignorals = intr.findPropertiesToIgnore(accessor);
            ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor);
            if (objectIdInfo == null) {
                // no ObjectId override, but maybe ObjectIdRef?
                if (oiw != null) {
                    objectIdInfo = intr.findObjectReferenceInfo(accessornew ObjectIdInfo(""nullnull));
                    oiw = .withAlwaysAsId(objectIdInfo.getAlwaysAsId());
                }
            } else {
                /* Ugh: mostly copied from BeanSerializerBase: but can't easily
                 * change it to be able to move to SerializerProvider (where it
                 * really belongs)
                 */
                
                // 2.1: allow modifications by "id ref" annotations as well:
                objectIdInfo = intr.findObjectReferenceInfo(accessorobjectIdInfo);
                ObjectIdGenerator<?> gen;
                Class<?> implClass = objectIdInfo.getGeneratorType();
                JavaType type = provider.constructType(implClass);
                JavaType idType = provider.getTypeFactory().findTypeParameters(typeObjectIdGenerator.class)[0];
                // Property-based generator is trickier
                if (implClass == ObjectIdGenerators.PropertyGenerator.class) { // most special one, needs extra work
                    String propName = objectIdInfo.getPropertyName();
                    BeanPropertyWriter idProp = null;
                    for (int i = 0, len = . ;; ++i) {
                        if (i == len) {
                            throw new IllegalArgumentException("Invalid Object Id definition for "+.getName()
                                    +": can not find property with name '"+propName+"'");
                        }
                        BeanPropertyWriter prop = [i];
                        if (propName.equals(prop.getName())) {
                            idProp = prop;
                            /* Let's force it to be the first property to output
                             * (although it may still get rearranged etc)
                             */
                            if (i > 0) { // note: must shuffle both regular properties and filtered
                                System.arraycopy(, 0, , 1, i);
                                [0] = idProp;
                                if ( != null) {
                                    BeanPropertyWriter fp = [i];
                                    System.arraycopy(, 0, , 1, i);
                                    [0] = fp;
                                }
                            }
                            break;
                        }
                    }
                    idType = idProp.getType();
                    gen = new PropertyBasedObjectIdGenerator(objectIdInfoidProp);
                    oiw = ObjectIdWriter.construct(idTypenullgenobjectIdInfo.getAlwaysAsId());
                } else { // other types need to be simpler
                    gen = provider.objectIdGeneratorInstance(accessorobjectIdInfo);
                    oiw = ObjectIdWriter.construct(idTypeobjectIdInfo.getPropertyName(), gen,
                            objectIdInfo.getAlwaysAsId());
                }
            }
        }
        // either way, need to resolve serializer:
        BeanSerializerBase contextual = this;
        if (oiw != null) {
            JsonSerializer<?> ser = provider.findValueSerializer(oiw.idTypeproperty);
            oiw = oiw.withSerializer(ser);
            if (oiw != ) {
                contextual = contextual.withObjectIdWriter(oiw);
            }
        }
        // And possibly add more properties to ignore
        if (ignorals != null && ignorals.length != 0) {
            contextual = contextual.withIgnorals(ignorals);
        }
        // One more thing: are we asked to serialize POJO as array?
        JsonFormat.Shape shape = null;
        if (accessor != null) {
            JsonFormat.Value format = intr.findFormat((Annotatedaccessor);
            if (format != null) {
                shape = format.getShape();
            }
        }
        if (shape == null) {
            shape = ;
        }
        if (shape == ..) {
            contextual = contextual.asArraySerializer();
        }
        return contextual;
    }
    
    /*
    /**********************************************************
    /* Partial JsonSerializer implementation
    /**********************************************************
     */
    @Override
    public boolean usesObjectId() {
        return ( != null);
    }
    
    // Main serialization method left unimplemented
    @Override
    public abstract void serialize(Object beanJsonGenerator jgenSerializerProvider provider)
        throws IOExceptionJsonGenerationException;
    // Type-info-augmented case implemented as it does not usually differ between impls
    @Override
    public void serializeWithType(Object beanJsonGenerator jgen,
            SerializerProvider providerTypeSerializer typeSer)
        throws IOExceptionJsonGenerationException
    {
        if ( != null) {
            _serializeWithObjectId(beanjgenprovidertypeSer);
            return;
        }
        String typeStr = ( == null) ? null :_customTypeId(bean);
        if (typeStr == null) {
            typeSer.writeTypePrefixForObject(beanjgen);
        } else {
            typeSer.writeCustomTypePrefixForObject(beanjgentypeStr);
        }
        if ( != null) {
            serializeFieldsFiltered(beanjgenprovider);
        } else {
            serializeFields(beanjgenprovider);
        }
        if (typeStr == null) {
            typeSer.writeTypeSuffixForObject(beanjgen);
        } else {
            typeSer.writeCustomTypeSuffixForObject(beanjgentypeStr);
        }
    }
    private final void _serializeWithObjectId(Object bean,
            JsonGenerator jgenSerializerProvider provider,
            TypeSerializer typeSer)
        throws IOExceptionJsonGenerationException
    {
        final ObjectIdWriter w = ;
        WritableObjectId oid = provider.findObjectId(beanw.generator);
        Object id = oid.id;
        
        if (id != null) { // have seen before; serialize just id
            oid.serializer.serialize(idjgenprovider);
            return;
        }
        // if not, bit more work:
        oid.serializer = w.serializer;
        oid.id = id = oid.generator.generateId(bean);
        
        String typeStr = ( == null) ? null :_customTypeId(bean);
        if (typeStr == null) {
            typeSer.writeTypePrefixForObject(beanjgen);
        } else {
            typeSer.writeCustomTypePrefixForObject(beanjgentypeStr);
        }
        // Very first thing: inject the id property
        SerializedString name = w.propertyName;
        if (name != null) {
            jgen.writeFieldName(name);
            w.serializer.serialize(idjgenprovider);
        }
        if ( != null) {
            serializeFieldsFiltered(beanjgenprovider);
        } else {
            serializeFields(beanjgenprovider);
        }
        if (typeStr == null) {
            typeSer.writeTypeSuffixForObject(beanjgen);
        } else {
            typeSer.writeCustomTypeSuffixForObject(beanjgentypeStr);
        }
    }
    
    private final String _customTypeId(Object bean)
    {
        final Object typeId = .getValue(bean);
        if (typeId == null) {
            return "";
        }
        return (typeId instanceof String) ? (StringtypeId : typeId.toString();
    }
    
    /*
    /**********************************************************
    /* Field serialization methods
    /**********************************************************
     */
    protected void serializeFields(Object beanJsonGenerator jgenSerializerProvider provider)
        throws IOExceptionJsonGenerationException
    {
        final BeanPropertyWriter[] props;
        if ( != null && provider.getSerializationView() != null) {
            props = ;
        } else {
            props = ;
        }
        int i = 0;
        try {
            for (final int len = props.lengthi < len; ++i) {
                BeanPropertyWriter prop = props[i];
                if (prop != null) { // can have nulls in filtered list
                    prop.serializeAsField(beanjgenprovider);
                }
            }
            if ( != null) {
                .getAndSerialize(beanjgenprovider);
            }
        } catch (Exception e) {
            String name = (i == props.length) ? "[anySetter]" : props[i].getName();
            wrapAndThrow(providerebeanname);
        } catch (StackOverflowError e) {
            /* 04-Sep-2009, tatu: Dealing with this is tricky, since we do not
             *   have many stack frames to spare... just one or two; can't
             *   make many calls.
             */
            JsonMappingException mapE = new JsonMappingException("Infinite recursion (StackOverflowError)"e);
            String name = (i == props.length) ? "[anySetter]" : props[i].getName();
            mapE.prependPath(new JsonMappingException.Reference(beanname));
            throw mapE;
        }
    }

    
Alternative serialization method that gets called when there is a com.fasterxml.jackson.databind.ser.BeanPropertyFilter that needs to be called to determine which properties are to be serialized (and possibly how)
    protected void serializeFieldsFiltered(Object beanJsonGenerator jgenSerializerProvider provider)
        throws IOExceptionJsonGenerationException
    {
        /* note: almost verbatim copy of "serializeFields"; copied (instead of merged)
         * so that old method need not add check for existence of filter.
         */
        
        final BeanPropertyWriter[] props;
        if ( != null && provider.getSerializationView() != null) {
            props = ;
        } else {
            props = ;
        }
        final BeanPropertyFilter filter = findFilter(provider);
        // better also allow missing filter actually..
        if (filter == null) {
            serializeFields(beanjgenprovider);
            return;
        }
        
        int i = 0;
        try {
            for (final int len = props.lengthi < len; ++i) {
                BeanPropertyWriter prop = props[i];
                if (prop != null) { // can have nulls in filtered list
                    filter.serializeAsField(beanjgenproviderprop);
                }
            }
            if ( != null) {
                .getAndSerialize(beanjgenprovider);
            }
        } catch (Exception e) {
            String name = (i == props.length) ? "[anySetter]" : props[i].getName();
            wrapAndThrow(providerebeanname);
        } catch (StackOverflowError e) {
            JsonMappingException mapE = new JsonMappingException("Infinite recursion (StackOverflowError)"e);
            String name = (i == props.length) ? "[anySetter]" : props[i].getName();
            mapE.prependPath(new JsonMappingException.Reference(beanname));
            throw mapE;
        }
    }

    
Helper method used to locate filter that is needed, based on filter id this serializer was constructed with.
    protected BeanPropertyFilter findFilter(SerializerProvider provider)
        throws JsonMappingException
    {
        final Object filterId = ;
        FilterProvider filters = provider.getFilterProvider();
        // Not ok to miss the provider, if a filter is declared to be needed.
        if (filters == null) {
            throw new JsonMappingException("Can not resolve BeanPropertyFilter with id '"+filterId+"'; no FilterProvider configured");
        }
        BeanPropertyFilter filter = filters.findFilter(filterId);
        // But whether unknown ids are ok just depends on filter provider; if we get null that's fine
        return filter;
    }
    
    @Override
    public JsonNode getSchema(SerializerProvider providerType typeHint)
        throws JsonMappingException
    {
        ObjectNode o = createSchemaNode("object"true);
        // [JACKSON-813]: Add optional JSON Schema id attribute, if found
        // NOTE: not optimal, does NOT go through AnnotationIntrospector etc:
        if (ann != null) {
            String id = ann.id();
            if (id != null && id.length() > 0) {
                o.put("id"id);
            }
        }
 
        //todo: should the classname go in the title?
        //o.put("title", _className);
        ObjectNode propertiesNode = o.objectNode();
        final BeanPropertyFilter filter;
        if ( != null) {
            filter = findFilter(provider);
        } else {
            filter = null;
        }
        		
        for (int i = 0; i < .i++) {
            BeanPropertyWriter prop = [i];
            if (filter == null) {
                prop.depositSchemaProperty(propertiesNodeprovider);
            } else {
                filter.depositSchemaProperty(proppropertiesNodeprovider);
            }
        }
        o.put("properties"propertiesNode);
        return o;
    }
    
    @Override
    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitorJavaType typeHint)
        throws JsonMappingException
    {
    	//deposit your output format 
    	JsonObjectFormatVisitor objectVisitor = visitor.expectObjectFormat(typeHint);
 
        if ( != null) {
            BeanPropertyFilter filter = findFilter(visitor.getProvider());
            for (int i = 0; i < .i++) {
                filter.depositSchemaProperty([i], objectVisitorvisitor.getProvider());
            }
        } else {
            for (int i = 0; i < .i++) {
                [i].depositSchemaProperty(objectVisitor);
            }
        }
    }
New to GrepCode? Check out our FAQ X