blob: 9b6e6021acb5d829587df32d1635922ef9b7d7ce [file] [log] [blame]
package com.fasterxml.jackson.databind.jsontype;
import java.io.IOException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.type.WritableTypeId;
import com.fasterxml.jackson.core.util.VersionUtil;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
/**
* Interface for serializing type information regarding instances of specified
* base type (super class), so that exact subtype can be properly deserialized
* later on. These instances are to be called by regular
* {@link com.fasterxml.jackson.databind.JsonSerializer}s using proper contextual
* calls, to add type information using mechanism type serializer was
* configured with.
*<p>
* NOTE: version 2.9 contains significant attempt at simplifying interface,
* as well as giving format implementation (via {@link JsonGenerator}) more
* control over actual serialization details. Minor changes are required to change
* call pattern so that return value of "prefix" write needs to be passed to "suffix"
* write.
*/
public abstract class TypeSerializer
{
/*
/**********************************************************
/* 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).
*
* @since 2.0
*/
public abstract TypeSerializer forProperty(BeanProperty prop);
/*
/**********************************************************
/* Introspection
/**********************************************************
*/
/**
* Accessor for type information inclusion method
* that serializer uses; indicates how type information
* is embedded in resulting JSON.
*/
public abstract JsonTypeInfo.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();
/*
/**********************************************************
/* Type serialization methods: new (2.9)
/**********************************************************
*/
/**
* Factory method for constructing type id value object to pass to
* {@link #writeTypePrefix}.
*/
public WritableTypeId typeId(Object value, JsonToken valueShape) {
WritableTypeId typeIdDef = new WritableTypeId(value, valueShape);
switch (getTypeInclusion()) {
case EXISTING_PROPERTY:
typeIdDef.include = WritableTypeId.Inclusion.PAYLOAD_PROPERTY;
typeIdDef.asProperty = getPropertyName();
break;
case EXTERNAL_PROPERTY:
typeIdDef.include = WritableTypeId.Inclusion.PARENT_PROPERTY;
typeIdDef.asProperty = getPropertyName();
break;
case PROPERTY:
typeIdDef.include = WritableTypeId.Inclusion.METADATA_PROPERTY;
typeIdDef.asProperty = getPropertyName();
break;
case WRAPPER_ARRAY:
typeIdDef.include = WritableTypeId.Inclusion.WRAPPER_ARRAY;
break;
case WRAPPER_OBJECT:
typeIdDef.include = WritableTypeId.Inclusion.WRAPPER_OBJECT;
break;
default:
VersionUtil.throwInternal();
}
return typeIdDef;
}
public WritableTypeId typeId(Object value, JsonToken valueShape,
Object id) {
WritableTypeId typeId = typeId(value, valueShape);
typeId.id = id;
return typeId;
}
public WritableTypeId typeId(Object value, Class<?> typeForId,
JsonToken valueShape) {
WritableTypeId typeId = typeId(value, valueShape);
typeId.forValueType = typeForId;
return typeId;
}
/**
* Method called to write initial part of type information for given
* value, along with possible wrapping to use: details are specified
* by `typeId` argument.
* Note that for structured types (Object, Array), this call will add
* necessary start token so it should NOT be explicitly written, unlike
* with non-type-id value writes.
*<p>
* See {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} for a complete
* example of typical usage.
*
* @param g Generator to use for outputting type id and possible wrapping
* @param typeId Details of what type id is to be written, how.
*
* @since 2.9
*/
public abstract WritableTypeId writeTypePrefix(JsonGenerator g,
WritableTypeId typeId) throws IOException;
/**
* Method that should be called after {@link #writeTypePrefix(JsonGenerator, WritableTypeId)}
* and matching value write have called, passing {@link WritableTypeId} returned.
* Usual idiom is:
*<pre>
* // Indicator generator that type identifier may be needed; generator may write
* // one as suggested, modify information, or take some other action
* // NOTE! For Object/Array types, this will ALSO write start marker!
* WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen,
* typeSer.typeId(value, JsonToken.START_OBJECT));
*
* // serializing actual value for which TypeId may have been written... like
* // NOTE: do NOT write START_OBJECT before OR END_OBJECT after:
* g.writeStringField("message", "Hello, world!"
*
* // matching type suffix call to let generator chance to add suffix, if any
* // NOTE! For Object/Array types, this will ALSO write end marker!
* typeSer.writeTypeSuffix(gen, typeIdDef);
*</pre>
*
* @since 2.9
*/
public abstract WritableTypeId writeTypeSuffix(JsonGenerator g,
WritableTypeId typeId) throws IOException;
/*
/**********************************************************
/* Legacy type serialization methods
/**********************************************************
*/
/**
* DEPRECATED: now equivalent to:
*{@code writeTypePrefix(g, typeId(value, JsonToken.VALUE_STRING));}.
* See {@link #writeTypePrefix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeTypePrefixForScalar(Object value, JsonGenerator g) throws IOException {
writeTypePrefix(g, typeId(value, JsonToken.VALUE_STRING));
}
/**
* DEPRECATED: now equivalent to:
*{@code writeTypePrefix(g, typeId(value, JsonToken.START_OBJECT));}.
* See {@link #writeTypePrefix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeTypePrefixForObject(Object value, JsonGenerator g) throws IOException {
writeTypePrefix(g, typeId(value, JsonToken.START_OBJECT));
}
/**
* DEPRECATED: now equivalent to:
*{@code writeTypePrefix(g, typeId(value, JsonToken.START_ARRAY));}.
* See {@link #writeTypePrefix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeTypePrefixForArray(Object value, JsonGenerator g) throws IOException {
writeTypePrefix(g, typeId(value, JsonToken.START_ARRAY));
}
/**
* DEPRECATED: now equivalent to:
*{@code writeTypeSuffix(g, typeId(value, JsonToken.VALUE_STRING));}.
* See {@link #writeTypeSuffix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeTypeSuffixForScalar(Object value, JsonGenerator g) throws IOException {
_writeLegacySuffix(g, typeId(value, JsonToken.VALUE_STRING));
}
/**
* DEPRECATED: now equivalent to:
*{@code writeTypeSuffix(g, typeId(value, JsonToken.START_OBJECT));}.
* See {@link #writeTypeSuffix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeTypeSuffixForObject(Object value, JsonGenerator g) throws IOException {
_writeLegacySuffix(g, typeId(value, JsonToken.START_OBJECT));
}
/**
* DEPRECATED: now equivalent to:
*{@code writeTypeSuffix(g, typeId(value, JsonToken.START_ARRAY));}.
* See {@link #writeTypeSuffix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeTypeSuffixForArray(Object value, JsonGenerator g) throws IOException {
_writeLegacySuffix(g, typeId(value, JsonToken.START_ARRAY));
}
/**
* DEPRECATED: now equivalent to:
*{@code writeTypePrefix(g, typeId(value, type, JsonToken.VALUE_STRING));}.
* See {@link #writeTypePrefix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeTypePrefixForScalar(Object value, JsonGenerator g, Class<?> type) throws IOException {
writeTypePrefix(g, typeId(value, type, JsonToken.VALUE_STRING));
}
/**
* DEPRECATED: now equivalent to:
*{@code writeTypePrefix(g, typeId(value, type, JsonToken.START_OBJECT));}.
* See {@link #writeTypePrefix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeTypePrefixForObject(Object value, JsonGenerator g, Class<?> type) throws IOException {
writeTypePrefix(g, typeId(value, type, JsonToken.START_OBJECT));
}
/**
* DEPRECATED: now equivalent to:
*{@code writeTypePrefix(g, typeId(value, type, JsonToken.START_ARRAY));}.
* See {@link #writeTypePrefix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeTypePrefixForArray(Object value, JsonGenerator g, Class<?> type) throws IOException {
writeTypePrefix(g, typeId(value, type, JsonToken.START_ARRAY));
}
/*
/**********************************************************
/* Type serialization methods with type id override
/**********************************************************
*/
/**
* DEPRECATED: now equivalent to:
*{@code writeTypePrefix(g, typeId(value, JsonToken.VALUE_STRING, typeId));}.
* See {@link #writeTypePrefix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeCustomTypePrefixForScalar(Object value, JsonGenerator g, String typeId) throws IOException {
writeTypePrefix(g, typeId(value, JsonToken.VALUE_STRING, typeId));
}
/**
* DEPRECATED: now equivalent to:
*{@code writeTypePrefix(g, typeId(value, JsonToken.START_OBJECT, typeId));}.
* See {@link #writeTypePrefix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeCustomTypePrefixForObject(Object value, JsonGenerator g, String typeId) throws IOException {
writeTypePrefix(g, typeId(value, JsonToken.START_OBJECT, typeId));
}
/**
* DEPRECATED: now equivalent to:
*{@code writeTypePrefix(g, typeId(value, JsonToken.START_ARRAY, typeId));}.
* See {@link #writeTypePrefix} for more info.
*
* @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeCustomTypePrefixForArray(Object value, JsonGenerator g, String typeId) throws IOException {
writeTypePrefix(g, typeId(value, JsonToken.START_ARRAY, typeId));
}
/**
* @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeCustomTypeSuffixForScalar(Object value, JsonGenerator g, String typeId) throws IOException {
_writeLegacySuffix(g, typeId(value, JsonToken.VALUE_STRING, typeId));
}
/**
* @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeCustomTypeSuffixForObject(Object value, JsonGenerator g, String typeId) throws IOException {
_writeLegacySuffix(g, typeId(value, JsonToken.START_OBJECT, typeId));
}
/**
* @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
*/
@Deprecated // since 2.9
public void writeCustomTypeSuffixForArray(Object value, JsonGenerator g, String typeId) throws IOException {
_writeLegacySuffix(g, typeId(value, JsonToken.START_ARRAY, typeId));
}
/**
* Helper method needed for backwards compatibility: since original type id
* can not be routed through completely, we have to reverse-engineer likely
* setting before calling suffix.
*
* @since 2.9
*/
protected final void _writeLegacySuffix(JsonGenerator g,
WritableTypeId typeId) throws IOException
{
// most likely logic within generator is this:
typeId.wrapperWritten = !g.canWriteTypeId();
writeTypeSuffix(g, typeId);
}
}