blob: 5173845efdc9dd7f17f40e5ca7aea27afcb2ba32 [file] [log] [blame]
package com.fasterxml.jackson.databind.jsontype;
import java.io.IOException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
/**
* Interface for deserializing type information from JSON content, to
* type-safely deserialize data into correct polymorphic instance
* (when type inclusion has been enabled for type handled).
*<p>
* Separate deserialization methods are needed because serialized
* form for inclusion mechanism {@link As#PROPERTY}
* is slighty different if value is not expressed as JSON Object:
* and as such both type deserializer and serializer need to
* JSON Object form (array, object or other (== scalar)) being used.
*/
public abstract class TypeDeserializer
{
/*
/**********************************************************
/* Initialization
/**********************************************************
*/
/**
* Method called to create contextual version, to be used for
* values of given property. This may be the type itself
* (as is the case for bean properties), or values contained
* (for {@link java.util.Collection} or {@link java.util.Map}
* valued properties).
*/
public abstract TypeDeserializer forProperty(BeanProperty prop);
/*
/**********************************************************
/* Introspection
/**********************************************************
*/
/**
* Accessor for type information inclusion method
* that deserializer uses; indicates how type information
* is (expected to be) embedded in JSON input.
*/
public abstract As getTypeInclusion();
/**
* Name of property that contains type information, if
* property-based inclusion is used.
*/
public abstract String getPropertyName();
/**
* Accessor for object that handles conversions between
* types and matching type ids.
*/
public abstract TypeIdResolver getTypeIdResolver();
/**
* Accessor for "default implementation" type; optionally defined
* class to use in cases where type id is not
* accessible for some reason (either missing, or cannot be
* resolved)
*/
public abstract Class<?> getDefaultImpl();
/*
/**********************************************************
/* Type deserialization methods
/**********************************************************
*/
/**
* Method called to let this type deserializer handle
* deserialization of "typed" object, when value itself
* is serialized as JSON Object (regardless of Java type).
* Method needs to figure out intended
* polymorphic type, locate {@link JsonDeserializer} to use, and
* call it with JSON data to deserializer (which does not contain
* type information).
*/
public abstract Object deserializeTypedFromObject(JsonParser p, DeserializationContext ctxt) throws IOException;
/**
* Method called to let this type deserializer handle
* deserialization of "typed" object, when value itself
* is serialized as JSON Array (regardless of Java type).
* Method needs to figure out intended
* polymorphic type, locate {@link JsonDeserializer} to use, and
* call it with JSON data to deserializer (which does not contain
* type information).
*/
public abstract Object deserializeTypedFromArray(JsonParser p, DeserializationContext ctxt) throws IOException;
/**
* Method called to let this type deserializer handle
* deserialization of "typed" object, when value itself
* is serialized as a scalar JSON value (something other
* than Array or Object), regardless of Java type.
* Method needs to figure out intended
* polymorphic type, locate {@link JsonDeserializer} to use, and
* call it with JSON data to deserializer (which does not contain
* type information).
*/
public abstract Object deserializeTypedFromScalar(JsonParser p, DeserializationContext ctxt) throws IOException;
/**
* Method called to let this type deserializer handle
* deserialization of "typed" object, when value itself
* may have been serialized using any kind of JSON value
* (Array, Object, scalar). Should only be called if JSON
* serialization is polymorphic (not Java type); for example when
* using JSON node representation, or "untyped" Java object
* (which may be Map, Collection, wrapper/primitive etc).
*/
public abstract Object deserializeTypedFromAny(JsonParser p, DeserializationContext ctxt) throws IOException;
/*
/**********************************************************
/* Shared helper methods
/**********************************************************
*/
/**
* Helper method used to check if given parser might be pointing to
* a "natural" value, and one that would be acceptable as the
* result value (compatible with declared base type)
*/
public static Object deserializeIfNatural(JsonParser p, DeserializationContext ctxt, JavaType baseType) throws IOException {
return deserializeIfNatural(p, ctxt, baseType.getRawClass());
}
@SuppressWarnings("incomplete-switch")
public static Object deserializeIfNatural(JsonParser p, DeserializationContext ctxt,
Class<?> base) throws IOException
{
final JsonToken t = p.currentToken();
if (t == null) {
return null;
}
switch (t) {
case VALUE_STRING:
if (base.isAssignableFrom(String.class)) {
return p.getText();
}
break;
case VALUE_NUMBER_INT:
if (base.isAssignableFrom(Integer.class)) {
return p.getIntValue();
}
break;
case VALUE_NUMBER_FLOAT:
if (base.isAssignableFrom(Double.class)) {
return Double.valueOf(p.getDoubleValue());
}
break;
case VALUE_TRUE:
if (base.isAssignableFrom(Boolean.class)) {
return Boolean.TRUE;
}
break;
case VALUE_FALSE:
if (base.isAssignableFrom(Boolean.class)) {
return Boolean.FALSE;
}
break;
}
return null;
}
}