1 package com.fasterxml.jackson.databind.jsontype;
2 
3 import java.io.IOException;
4 
5 import com.fasterxml.jackson.core.*;
6 import com.fasterxml.jackson.core.type.WritableTypeId;
7 import com.fasterxml.jackson.core.util.VersionUtil;
8 import com.fasterxml.jackson.databind.BeanProperty;
9 import com.fasterxml.jackson.annotation.JsonTypeInfo;
10 
11 /**
12  * Interface for serializing type information regarding instances of specified
13  * base type (super class), so that exact subtype can be properly deserialized
14  * later on. These instances are to be called by regular
15  * {@link com.fasterxml.jackson.databind.JsonSerializer}s using proper contextual
16  * calls, to add type information using mechanism type serializer was
17  * configured with.
18  *<p>
19  * NOTE: version 2.9 contains significant attempt at simplifying interface,
20  * as well as giving format implementation (via {@link JsonGenerator}) more
21  * control over actual serialization details. Minor changes are required to change
22  * call pattern so that return value of "prefix" write needs to be passed to "suffix"
23  * write.
24  */
25 public abstract class TypeSerializer
26 {
27     /*
28     /**********************************************************
29     /* Initialization
30     /**********************************************************
31      */
32 
33     /**
34      * Method called to create contextual version, to be used for
35      * values of given property. This may be the type itself
36      * (as is the case for bean properties), or values contained
37      * (for {@link java.util.Collection} or {@link java.util.Map}
38      * valued properties).
39      *
40      * @since 2.0
41      */
forProperty(BeanProperty prop)42     public abstract TypeSerializer forProperty(BeanProperty prop);
43 
44     /*
45     /**********************************************************
46     /* Introspection
47     /**********************************************************
48      */
49 
50     /**
51      * Accessor for type information inclusion method
52      * that serializer uses; indicates how type information
53      * is embedded in resulting JSON.
54      */
getTypeInclusion()55     public abstract JsonTypeInfo.As getTypeInclusion();
56 
57     /**
58      * Name of property that contains type information, if
59      * property-based inclusion is used.
60      */
getPropertyName()61     public abstract String getPropertyName();
62 
63     /**
64      * Accessor for object that handles conversions between
65      * types and matching type ids.
66      */
getTypeIdResolver()67     public abstract TypeIdResolver getTypeIdResolver();
68 
69     /*
70     /**********************************************************
71     /* Type serialization methods: new (2.9)
72     /**********************************************************
73      */
74 
75     /**
76      * Factory method for constructing type id value object to pass to
77      * {@link #writeTypePrefix}.
78      */
typeId(Object value, JsonToken valueShape)79     public WritableTypeId typeId(Object value, JsonToken valueShape) {
80         WritableTypeId typeIdDef = new WritableTypeId(value, valueShape);
81         switch (getTypeInclusion()) {
82         case EXISTING_PROPERTY:
83             typeIdDef.include = WritableTypeId.Inclusion.PAYLOAD_PROPERTY;
84             typeIdDef.asProperty = getPropertyName();
85             break;
86         case EXTERNAL_PROPERTY:
87             typeIdDef.include = WritableTypeId.Inclusion.PARENT_PROPERTY;
88             typeIdDef.asProperty = getPropertyName();
89             break;
90         case PROPERTY:
91             typeIdDef.include = WritableTypeId.Inclusion.METADATA_PROPERTY;
92             typeIdDef.asProperty = getPropertyName();
93             break;
94         case WRAPPER_ARRAY:
95             typeIdDef.include = WritableTypeId.Inclusion.WRAPPER_ARRAY;
96             break;
97         case WRAPPER_OBJECT:
98             typeIdDef.include = WritableTypeId.Inclusion.WRAPPER_OBJECT;
99             break;
100         default:
101             VersionUtil.throwInternal();
102         }
103         return typeIdDef;
104     }
105 
typeId(Object value, JsonToken valueShape, Object id)106     public WritableTypeId typeId(Object value, JsonToken valueShape,
107             Object id) {
108         WritableTypeId typeId = typeId(value, valueShape);
109         typeId.id = id;
110         return typeId;
111     }
112 
typeId(Object value, Class<?> typeForId, JsonToken valueShape)113     public WritableTypeId typeId(Object value, Class<?> typeForId,
114             JsonToken valueShape) {
115         WritableTypeId typeId = typeId(value, valueShape);
116         typeId.forValueType = typeForId;
117         return typeId;
118     }
119 
120     /**
121      * Method called to write initial part of type information for given
122      * value, along with possible wrapping to use: details are specified
123      * by `typeId` argument.
124      * Note that for structured types (Object, Array), this call will add
125      * necessary start token so it should NOT be explicitly written, unlike
126      * with non-type-id value writes.
127      *<p>
128      * See {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} for a complete
129      * example of typical usage.
130      *
131      * @param g Generator to use for outputting type id and possible wrapping
132      * @param typeId Details of what type id is to be written, how.
133      *
134      * @since 2.9
135      */
writeTypePrefix(JsonGenerator g, WritableTypeId typeId)136     public abstract WritableTypeId writeTypePrefix(JsonGenerator g,
137             WritableTypeId typeId) throws IOException;
138 
139     /**
140      * Method that should be called after {@link #writeTypePrefix(JsonGenerator, WritableTypeId)}
141      * and matching value write have been called, passing {@link WritableTypeId} returned.
142      * Usual idiom is:
143      *<pre>
144      * // Indicator generator that type identifier may be needed; generator may write
145      * // one as suggested, modify information, or take some other action
146      * // NOTE! For Object/Array types, this will ALSO write start marker!
147      * WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen,
148      *          typeSer.typeId(value, JsonToken.START_OBJECT));
149      *
150      * // serializing actual value for which TypeId may have been written... like
151      * // NOTE: do NOT write START_OBJECT before OR END_OBJECT after:
152      * g.writeStringField("message", "Hello, world!"
153      *
154      * // matching type suffix call to let generator chance to add suffix, if any
155      * // NOTE! For Object/Array types, this will ALSO write end marker!
156      * typeSer.writeTypeSuffix(gen, typeIdDef);
157      *</pre>
158      *
159      * @since 2.9
160      */
writeTypeSuffix(JsonGenerator g, WritableTypeId typeId)161     public abstract WritableTypeId writeTypeSuffix(JsonGenerator g,
162             WritableTypeId typeId) throws IOException;
163 
164     /*
165     /**********************************************************
166     /* Legacy type serialization methods
167     /**********************************************************
168      */
169 
170     /**
171      * DEPRECATED: now equivalent to:
172      *{@code writeTypePrefix(g, typeId(value, JsonToken.VALUE_STRING));}.
173      * See {@link #writeTypePrefix} for more info.
174      *
175      * @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
176      */
177     @Deprecated // since 2.9
writeTypePrefixForScalar(Object value, JsonGenerator g)178     public void writeTypePrefixForScalar(Object value, JsonGenerator g) throws IOException {
179         writeTypePrefix(g, typeId(value, JsonToken.VALUE_STRING));
180     }
181 
182     /**
183      * DEPRECATED: now equivalent to:
184      *{@code writeTypePrefix(g, typeId(value, JsonToken.START_OBJECT));}.
185      * See {@link #writeTypePrefix} for more info.
186      *
187      * @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
188      */
189     @Deprecated // since 2.9
writeTypePrefixForObject(Object value, JsonGenerator g)190     public void writeTypePrefixForObject(Object value, JsonGenerator g) throws IOException {
191         writeTypePrefix(g, typeId(value, JsonToken.START_OBJECT));
192     }
193 
194     /**
195      * DEPRECATED: now equivalent to:
196      *{@code writeTypePrefix(g, typeId(value, JsonToken.START_ARRAY));}.
197      * See {@link #writeTypePrefix} for more info.
198      *
199      * @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
200      */
201     @Deprecated // since 2.9
writeTypePrefixForArray(Object value, JsonGenerator g)202     public void writeTypePrefixForArray(Object value, JsonGenerator g) throws IOException {
203         writeTypePrefix(g, typeId(value, JsonToken.START_ARRAY));
204     }
205 
206     /**
207      * DEPRECATED: now equivalent to:
208      *{@code writeTypeSuffix(g, typeId(value, JsonToken.VALUE_STRING));}.
209      * See {@link #writeTypeSuffix} for more info.
210      *
211      * @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
212      */
213     @Deprecated // since 2.9
writeTypeSuffixForScalar(Object value, JsonGenerator g)214     public void writeTypeSuffixForScalar(Object value, JsonGenerator g) throws IOException {
215         _writeLegacySuffix(g, typeId(value, JsonToken.VALUE_STRING));
216     }
217 
218     /**
219      * DEPRECATED: now equivalent to:
220      *{@code writeTypeSuffix(g, typeId(value, JsonToken.START_OBJECT));}.
221      * See {@link #writeTypeSuffix} for more info.
222      *
223      * @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
224      */
225     @Deprecated // since 2.9
writeTypeSuffixForObject(Object value, JsonGenerator g)226     public void writeTypeSuffixForObject(Object value, JsonGenerator g) throws IOException {
227         _writeLegacySuffix(g, typeId(value, JsonToken.START_OBJECT));
228     }
229 
230     /**
231      * DEPRECATED: now equivalent to:
232      *{@code writeTypeSuffix(g, typeId(value, JsonToken.START_ARRAY));}.
233      * See {@link #writeTypeSuffix} for more info.
234      *
235      * @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
236      */
237     @Deprecated // since 2.9
writeTypeSuffixForArray(Object value, JsonGenerator g)238     public void writeTypeSuffixForArray(Object value, JsonGenerator g) throws IOException {
239         _writeLegacySuffix(g, typeId(value, JsonToken.START_ARRAY));
240     }
241 
242     /**
243      * DEPRECATED: now equivalent to:
244      *{@code writeTypePrefix(g, typeId(value, type, JsonToken.VALUE_STRING));}.
245      * See {@link #writeTypePrefix} for more info.
246      *
247      * @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
248      */
249     @Deprecated // since 2.9
writeTypePrefixForScalar(Object value, JsonGenerator g, Class<?> type)250     public void writeTypePrefixForScalar(Object value, JsonGenerator g, Class<?> type) throws IOException {
251         writeTypePrefix(g, typeId(value, type, JsonToken.VALUE_STRING));
252     }
253 
254     /**
255      * DEPRECATED: now equivalent to:
256      *{@code writeTypePrefix(g, typeId(value, type, JsonToken.START_OBJECT));}.
257      * See {@link #writeTypePrefix} for more info.
258      *
259      * @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
260      */
261     @Deprecated // since 2.9
writeTypePrefixForObject(Object value, JsonGenerator g, Class<?> type)262     public void writeTypePrefixForObject(Object value, JsonGenerator g, Class<?> type) throws IOException {
263         writeTypePrefix(g, typeId(value, type, JsonToken.START_OBJECT));
264     }
265 
266     /**
267      * DEPRECATED: now equivalent to:
268      *{@code writeTypePrefix(g, typeId(value, type, JsonToken.START_ARRAY));}.
269      * See {@link #writeTypePrefix} for more info.
270      *
271      * @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
272      */
273     @Deprecated // since 2.9
writeTypePrefixForArray(Object value, JsonGenerator g, Class<?> type)274     public void writeTypePrefixForArray(Object value, JsonGenerator g, Class<?> type) throws IOException {
275         writeTypePrefix(g, typeId(value, type, JsonToken.START_ARRAY));
276     }
277 
278     /*
279     /**********************************************************
280     /* Type serialization methods with type id override
281     /**********************************************************
282      */
283 
284     /**
285      * DEPRECATED: now equivalent to:
286      *{@code writeTypePrefix(g, typeId(value, JsonToken.VALUE_STRING, typeId));}.
287      * See {@link #writeTypePrefix} for more info.
288      *
289      * @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
290      */
291     @Deprecated // since 2.9
writeCustomTypePrefixForScalar(Object value, JsonGenerator g, String typeId)292     public void writeCustomTypePrefixForScalar(Object value, JsonGenerator g, String typeId) throws IOException {
293         writeTypePrefix(g, typeId(value, JsonToken.VALUE_STRING, typeId));
294     }
295 
296     /**
297      * DEPRECATED: now equivalent to:
298      *{@code writeTypePrefix(g, typeId(value, JsonToken.START_OBJECT, typeId));}.
299      * See {@link #writeTypePrefix} for more info.
300      *
301      * @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
302      */
303     @Deprecated // since 2.9
writeCustomTypePrefixForObject(Object value, JsonGenerator g, String typeId)304     public void writeCustomTypePrefixForObject(Object value, JsonGenerator g, String typeId) throws IOException {
305         writeTypePrefix(g, typeId(value, JsonToken.START_OBJECT, typeId));
306     }
307 
308     /**
309      * DEPRECATED: now equivalent to:
310      *{@code writeTypePrefix(g, typeId(value, JsonToken.START_ARRAY, typeId));}.
311      * See {@link #writeTypePrefix} for more info.
312      *
313      * @deprecated Since 2.9 use {@link #writeTypePrefix(JsonGenerator, WritableTypeId)} instead
314      */
315     @Deprecated // since 2.9
writeCustomTypePrefixForArray(Object value, JsonGenerator g, String typeId)316     public void writeCustomTypePrefixForArray(Object value, JsonGenerator g, String typeId) throws IOException {
317         writeTypePrefix(g, typeId(value, JsonToken.START_ARRAY, typeId));
318     }
319 
320     /**
321      * @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
322      */
323     @Deprecated // since 2.9
writeCustomTypeSuffixForScalar(Object value, JsonGenerator g, String typeId)324     public void writeCustomTypeSuffixForScalar(Object value, JsonGenerator g, String typeId) throws IOException {
325         _writeLegacySuffix(g, typeId(value, JsonToken.VALUE_STRING, typeId));
326     }
327 
328     /**
329      * @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
330      */
331     @Deprecated // since 2.9
writeCustomTypeSuffixForObject(Object value, JsonGenerator g, String typeId)332     public void writeCustomTypeSuffixForObject(Object value, JsonGenerator g, String typeId) throws IOException {
333         _writeLegacySuffix(g, typeId(value, JsonToken.START_OBJECT, typeId));
334     }
335 
336     /**
337      * @deprecated Since 2.9 use {@link #writeTypeSuffix(JsonGenerator, WritableTypeId)} instead
338      */
339     @Deprecated // since 2.9
writeCustomTypeSuffixForArray(Object value, JsonGenerator g, String typeId)340     public void writeCustomTypeSuffixForArray(Object value, JsonGenerator g, String typeId) throws IOException {
341         _writeLegacySuffix(g, typeId(value, JsonToken.START_ARRAY, typeId));
342     }
343 
344     /**
345      * Helper method needed for backwards compatibility: since original type id
346      * can not be routed through completely, we have to reverse-engineer likely
347      * setting before calling suffix.
348      *
349      * @since 2.9
350      */
_writeLegacySuffix(JsonGenerator g, WritableTypeId typeId)351     protected final void _writeLegacySuffix(JsonGenerator g,
352             WritableTypeId typeId) throws IOException
353     {
354         // most likely logic within generator is this:
355         typeId.wrapperWritten = !g.canWriteTypeId();
356         writeTypeSuffix(g, typeId);
357     }
358 }
359