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