| 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); |
| } |
| } |