Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.fasterxml.jackson.databind.ser.std;
  
  
 
Serializer class that can serialize Object that have a com.fasterxml.jackson.annotation.JsonValue annotation to indicate that serialization should be done by calling the method annotated, and serializing result it returns.

Implementation note: we will post-process resulting serializer (much like what is done with com.fasterxml.jackson.databind.ser.BeanSerializer) to figure out actual serializers for final types. This must be done from createContextual(com.fasterxml.jackson.databind.SerializerProvider,com.fasterxml.jackson.databind.BeanProperty) method, and NOT from constructor; otherwise we could end up with an infinite loop.

 
 public class JsonValueSerializer
     extends StdSerializer<Object>
 {
     protected final Method _accessorMethod;
 
     protected final JsonSerializer<Object_valueSerializer;
 
     protected final BeanProperty _property;
    
    
This is a flag that is set in rare (?) cases where this serializer is used for "natural" types (boolean, int, String, double); and where we actually must force type information wrapping, even though one would not normally be added.
 
     protected final boolean _forceTypeInformation;
     
     /*
     /**********************************************************
     /* Life-cycle
     /**********************************************************
      */

    

Parameters:
ser Explicit serializer to use, if caller knows it (which occurs if and only if the "value method" was annotated with com.fasterxml.jackson.databind.annotation.JsonSerialize.using()), otherwise null
 
     public JsonValueSerializer(Method valueMethodJsonSerializer<Objectser)
     {
         super(Object.class);
          = valueMethod;
          = ser;
          = null;
          = true// gets reconsidered when we are contextualized
     }
 
     @SuppressWarnings("unchecked")
     public JsonValueSerializer(JsonValueSerializer srcBeanProperty property,
             JsonSerializer<?> serboolean forceTypeInfo)
     {
         super(Object.class);
          = src._accessorMethod;
          = (JsonSerializer<Object>) ser;
          = property;
          = forceTypeInfo;
     }
 
     public JsonValueSerializer withResolved(BeanProperty property,
             JsonSerializer<?> serboolean forceTypeInfo)
     {
         if ( == property &&  == ser
                 && forceTypeInfo == ) {
             return this;
         }
         return new JsonValueSerializer(thispropertyserforceTypeInfo);
     }
     
     /*
     /**********************************************************
     /* Post-processing
     /**********************************************************
      */

    
We can try to find the actual serializer for value, if we can statically figure out what the result type must be.
//  @Override
            BeanProperty property)
        throws JsonMappingException
    {
        JsonSerializer<?> ser = ;
        if (ser == null) {
            /* Can only assign serializer statically if the declared type is final:
             * if not, we don't really know the actual type until we get the instance.
             */
            // 10-Mar-2010, tatu: Except if static typing is to be used
            if (provider.isEnabled(.)
                    || Modifier.isFinal(.getReturnType().getModifiers())) {
                JavaType t = provider.constructType(.getGenericReturnType());
                // false -> no need to cache
                /* 10-Mar-2010, tatu: Ideally we would actually separate out type
                 *   serializer from value serializer; but, alas, there's no access
                 *   to serializer factory at this point... 
                 */
                /* 09-Dec-2010, tatu: Turns out we must add special handling for
                 *   cases where "native" (aka "natural") type is being serialized,
                 *   using standard serializer
                 */
                ser = provider.findTypedValueSerializer(tfalse);
                boolean forceTypeInformation = isNaturalTypeWithStdHandling(t.getRawClass(), ser);
                return withResolved(propertyserforceTypeInformation);
            }
        } else if (ser instanceof ContextualSerializer) {
            ser = ((ContextualSerializerser).createContextual(providerproperty);
            return withResolved(propertyser);
        }
        return this;
    }
    
    /*
    /**********************************************************
    /* Actual serialization
    /**********************************************************
     */
    
    @Override
    public void serialize(Object beanJsonGenerator jgenSerializerProvider prov)
        throws IOExceptionJsonGenerationException
    {
        try {
            Object value = .invoke(bean);
            if (value == null) {
                prov.defaultSerializeNull(jgen);
                return;
            }
            JsonSerializer<Objectser = ;
            if (ser == null) {
                Class<?> c = value.getClass();
                /* 10-Mar-2010, tatu: Ideally we would actually separate out type
                 *   serializer from value serializer; but, alas, there's no access
                 *   to serializer factory at this point... 
                 */
                // let's cache it, may be needed soon again
                ser = prov.findTypedValueSerializer(ctrue);
            }
            ser.serialize(valuejgenprov);
        } catch (IOException ioe) {
            throw ioe;
        } catch (Exception e) {
            Throwable t = e;
            // Need to unwrap this specific type, to see infinite recursion...
            while (t instanceof InvocationTargetException && t.getCause() != null) {
                t = t.getCause();
            }
            // Errors shouldn't be wrapped (and often can't, as well)
            if (t instanceof Error) {
                throw (Errort;
            }
            // let's try to indicate the path best we can...
            throw JsonMappingException.wrapWithPath(tbean.getName() + "()");
        }
    }
    @Override
    public void serializeWithType(Object beanJsonGenerator jgenSerializerProvider provider,
            TypeSerializer typeSer)
        throws IOExceptionJsonProcessingException
    {
        // Regardless of other parts, first need to find value to serialize:
        Object value = null;
        try {
            value = .invoke(bean);
            // and if we got null, can also just write it directly
            if (value == null) {
                provider.defaultSerializeNull(jgen);
                return;
            }
            JsonSerializer<Objectser = ;
            if (ser != null) { // already got a serializer? fabulous, that be easy...
                /* 09-Dec-2010, tatu: To work around natural type's refusal to add type info, we do
                 *    this (note: type is for the wrapper type, not enclosed value!)
                 */
                if () {
                    typeSer.writeTypePrefixForScalar(beanjgen);
                } 
                ser.serializeWithType(valuejgenprovidertypeSer);
                if () {
                    typeSer.writeTypeSuffixForScalar(beanjgen);
                } 
                return;
            }
            // But if not, it gets tad trickier (copied from main serialize() method)
            Class<?> c = value.getClass();
            ser = provider.findTypedValueSerializer(ctrue);
            // note: now we have bundled type serializer, so should NOT call with typed version
            ser.serialize(valuejgenprovider);
        } catch (IOException ioe) {
            throw ioe;
        } catch (Exception e) {
            Throwable t = e;
            // Need to unwrap this specific type, to see infinite recursion...
            while (t instanceof InvocationTargetException && t.getCause() != null) {
                t = t.getCause();
            }
            // Errors shouldn't be wrapped (and often can't, as well)
            if (t instanceof Error) {
                throw (Errort;
            }
            // let's try to indicate the path best we can...
            throw JsonMappingException.wrapWithPath(tbean.getName() + "()");
        }
    }
    
    @Override
    public JsonNode getSchema(SerializerProvider providerType typeHint)
        throws JsonMappingException
    {
        return ( instanceof SchemaAware) ?
                ((SchemaAware).getSchema(providernull) :
                JsonSchema.getDefaultSchemaNode();
    }
    
    @Override
    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitorJavaType typeHint)
        throws JsonMappingException
    {
        if ( != null) {
            .acceptJsonFormatVisitor(visitornull); 
        } else {
            visitor.expectAnyFormat(typeHint);
    	}
    }
    protected boolean isNaturalTypeWithStdHandling(Class<?> rawTypeJsonSerializer<?> ser)
    {
        // First: do we have a natural type being handled?
        if (rawType.isPrimitive()) {
            if (rawType != . && rawType != . && rawType != .) {
                return false;
            }
        } else {
            if (rawType != String.class &&
                    rawType != Integer.class && rawType != Boolean.class && rawType != Double.class) {
                return false;
            }
        }
        return isDefaultSerializer(ser);
    }
    
    /*
    /**********************************************************
    /* Other methods
    /**********************************************************
     */
    @Override
    public String toString()
    {
        return "(@JsonValue serializer for method " + .getDeclaringClass() + "#" + .getName() + ")";
    }
New to GrepCode? Check out our FAQ X