1 package com.fasterxml.jackson.databind; 2 3 import java.io.IOException; 4 import java.util.Iterator; 5 6 import com.fasterxml.jackson.core.*; 7 8 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable; 9 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; 10 import com.fasterxml.jackson.databind.jsontype.TypeSerializer; 11 import com.fasterxml.jackson.databind.ser.PropertyWriter; 12 import com.fasterxml.jackson.databind.util.ClassUtil; 13 import com.fasterxml.jackson.databind.util.NameTransformer; 14 15 /** 16 * Abstract class that defines API used by {@link ObjectMapper} (and 17 * other chained {@link JsonSerializer}s too) to serialize Objects of 18 * arbitrary types into JSON, using provided {@link JsonGenerator}. 19 * {@link com.fasterxml.jackson.databind.ser.std.StdSerializer} instead 20 * of this class, since it will implement many of optional 21 * methods of this class. 22 *<p> 23 * NOTE: various <code>serialize</code> methods are never (to be) called 24 * with null values -- caller <b>must</b> handle null values, usually 25 * by calling {@link SerializerProvider#findNullValueSerializer} to obtain 26 * serializer to use. 27 * This also means that custom serializers cannot be directly used to change 28 * the output to produce when serializing null values. 29 *<p> 30 * If serializer is an aggregate one -- meaning it delegates handling of some 31 * of its contents by using other serializer(s) -- it typically also needs 32 * to implement {@link com.fasterxml.jackson.databind.ser.ResolvableSerializer}, 33 * which can locate secondary serializers needed. This is important to allow dynamic 34 * overrides of serializers; separate call interface is needed to separate 35 * resolution of secondary serializers (which may have cyclic link back 36 * to serializer itself, directly or indirectly). 37 *<p> 38 * In addition, to support per-property annotations (to configure aspects 39 * of serialization on per-property basis), serializers may want 40 * to implement 41 * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer}, 42 * which allows specialization of serializers: call to 43 * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer#createContextual} 44 * is passed information on property, and can create a newly configured 45 * serializer for handling that particular property. 46 *<p> 47 * If both 48 * {@link com.fasterxml.jackson.databind.ser.ResolvableSerializer} and 49 * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer} 50 * are implemented, resolution of serializers occurs before 51 * contextualization. 52 */ 53 public abstract class JsonSerializer<T> 54 implements JsonFormatVisitable // since 2.1 55 { 56 /* 57 /********************************************************** 58 /* Fluent factory methods for constructing decorated versions 59 /********************************************************** 60 */ 61 62 /** 63 * Method that will return serializer instance that produces 64 * "unwrapped" serialization, if applicable for type being 65 * serialized (which is the case for some serializers 66 * that produce JSON Objects as output). 67 * If no unwrapped serializer can be constructed, will simply 68 * return serializer as-is. 69 *<p> 70 * Default implementation just returns serializer as-is, 71 * indicating that no unwrapped variant exists 72 * 73 * @param unwrapper Name transformation to use to convert between names 74 * of unwrapper properties 75 */ unwrappingSerializer(NameTransformer unwrapper)76 public JsonSerializer<T> unwrappingSerializer(NameTransformer unwrapper) { 77 return this; 78 } 79 80 /** 81 * Method that can be called to try to replace serializer this serializer 82 * delegates calls to. If not supported (either this serializer does not 83 * delegate anything; or it does not want any changes), should either 84 * throw {@link UnsupportedOperationException} (if operation does not 85 * make sense or is not allowed); or return this serializer as is. 86 * 87 * @since 2.1 88 */ replaceDelegatee(JsonSerializer<?> delegatee)89 public JsonSerializer<T> replaceDelegatee(JsonSerializer<?> delegatee) { 90 throw new UnsupportedOperationException(); 91 } 92 93 /** 94 * Mutant factory method that is called if contextual configuration indicates that 95 * a specific filter (as specified by <code>filterId</code>) is to be used for 96 * serialization. 97 *<p> 98 * Default implementation simply returns <code>this</code>; sub-classes that do support 99 * filtering will need to create and return new instance if filter changes. 100 * 101 * @since 2.6 102 */ withFilterId(Object filterId)103 public JsonSerializer<?> withFilterId(Object filterId) { 104 return this; 105 } 106 107 /* 108 /********************************************************** 109 /* Serialization methods 110 /********************************************************** 111 */ 112 113 /** 114 * Method that can be called to ask implementation to serialize 115 * values of type this serializer handles. 116 * 117 * @param value Value to serialize; can <b>not</b> be null. 118 * @param gen Generator used to output resulting Json content 119 * @param serializers Provider that can be used to get serializers for 120 * serializing Objects value contains, if any. 121 */ serialize(T value, JsonGenerator gen, SerializerProvider serializers)122 public abstract void serialize(T value, JsonGenerator gen, SerializerProvider serializers) 123 throws IOException; 124 125 /** 126 * Method that can be called to ask implementation to serialize 127 * values of type this serializer handles, using specified type serializer 128 * for embedding necessary type information. 129 *<p> 130 * Default implementation will throw {@link UnsupportedOperationException} 131 * to indicate that proper type handling needs to be implemented. 132 *<p> 133 * For simple datatypes written as a single scalar value (JSON String, Number, Boolean), 134 * implementation would look like: 135 *<pre> 136 * // note: method to call depends on whether this type is serialized as JSON scalar, object or Array! 137 * typeSer.writeTypePrefixForScalar(value, gen); 138 * serialize(value, gen, provider); 139 * typeSer.writeTypeSuffixForScalar(value, gen); 140 *</pre> 141 * and implementations for type serialized as JSON Arrays or Objects would differ slightly, 142 * as <code>START-ARRAY</code>/<code>END-ARRAY</code> and 143 * <code>START-OBJECT</code>/<code>END-OBJECT</code> pairs 144 * need to be properly handled with respect to serializing of contents. 145 * 146 * @param value Value to serialize; can <b>not</b> be null. 147 * @param gen Generator used to output resulting Json content 148 * @param serializers Provider that can be used to get serializers for 149 * serializing Objects value contains, if any. 150 * @param typeSer Type serializer to use for including type information 151 */ serializeWithType(T value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer)152 public void serializeWithType(T value, JsonGenerator gen, SerializerProvider serializers, 153 TypeSerializer typeSer) 154 throws IOException 155 { 156 Class<?> clz = handledType(); 157 if (clz == null) { 158 clz = value.getClass(); 159 } 160 serializers.reportBadDefinition(clz, String.format( 161 "Type id handling not implemented for type %s (by serializer of type %s)", 162 clz.getName(), getClass().getName())); 163 } 164 165 /* 166 /********************************************************** 167 /* Other accessors 168 /********************************************************** 169 */ 170 171 /** 172 * Method for accessing type of Objects this serializer can handle. 173 * Note that this information is not guaranteed to be exact -- it 174 * may be a more generic (super-type) -- but it should not be 175 * incorrect (return a non-related type). 176 *<p> 177 * Default implementation will return null, which essentially means 178 * same as returning <code>Object.class</code> would; that is, that 179 * nothing is known about handled type. 180 *<p> 181 */ handledType()182 public Class<T> handledType() { return null; } 183 184 /** 185 * Method called to check whether given serializable value is 186 * considered "empty" value (for purposes of suppressing serialization 187 * of empty values). 188 *<p> 189 * Default implementation will consider only null values to be empty. 190 * 191 * @deprecated Since 2.5 Use {@link #isEmpty(SerializerProvider, Object)} instead; 192 * will be removed from 3.0 193 */ 194 @Deprecated isEmpty(T value)195 public boolean isEmpty(T value) { 196 return isEmpty(null, value); 197 } 198 199 /** 200 * Method called to check whether given serializable value is 201 * considered "empty" value (for purposes of suppressing serialization 202 * of empty values). 203 *<p> 204 * Default implementation will consider only null values to be empty. 205 *<p> 206 * NOTE: replaces {@link #isEmpty(Object)}, which was deprecated in 2.5 207 * 208 * @since 2.5 209 */ isEmpty(SerializerProvider provider, T value)210 public boolean isEmpty(SerializerProvider provider, T value) { 211 return (value == null); 212 } 213 214 /** 215 * Method that can be called to see whether this serializer instance 216 * will use Object Id to handle cyclic references. 217 */ usesObjectId()218 public boolean usesObjectId() { 219 return false; 220 } 221 222 /** 223 * Accessor for checking whether this serializer is an 224 * "unwrapping" serializer; this is necessary to know since 225 * it may also require caller to suppress writing of the 226 * leading property name. 227 */ isUnwrappingSerializer()228 public boolean isUnwrappingSerializer() { 229 return false; 230 } 231 232 /** 233 * Accessor that can be used to determine if this serializer uses 234 * another serializer for actual serialization, by delegating 235 * calls. If so, will return immediate delegate (which itself may 236 * delegate to further serializers); otherwise will return null. 237 * 238 * @return Serializer this serializer delegates calls to, if null; 239 * null otherwise. 240 * 241 * @since 2.1 242 */ getDelegatee()243 public JsonSerializer<?> getDelegatee() { 244 return null; 245 } 246 247 /** 248 * Accessor for iterating over logical properties that the type 249 * handled by this serializer has, from serialization perspective. 250 * Actual type of properties, if any, will be 251 * {@link com.fasterxml.jackson.databind.ser.BeanPropertyWriter}. 252 * Of standard Jackson serializers, only {@link com.fasterxml.jackson.databind.ser.BeanSerializer} 253 * exposes properties. 254 * 255 * @since 2.6 256 */ properties()257 public Iterator<PropertyWriter> properties() { 258 return ClassUtil.emptyIterator(); 259 } 260 261 /* 262 /********************************************************** 263 /* Default JsonFormatVisitable implementation 264 /********************************************************** 265 */ 266 267 /** 268 * Default implementation simply calls {@link JsonFormatVisitorWrapper#expectAnyFormat(JavaType)}. 269 * 270 * @since 2.1 271 */ 272 @Override acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType type)273 public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType type) 274 throws JsonMappingException 275 { 276 visitor.expectAnyFormat(type); 277 } 278 279 /* 280 /********************************************************** 281 /* Helper class(es) 282 /********************************************************** 283 */ 284 285 /** 286 * This marker class is only to be used with annotations, to 287 * indicate that <b>no serializer is configured</b>. 288 *<p> 289 * Specifically, this class is to be used as the marker for 290 * annotation {@link com.fasterxml.jackson.databind.annotation.JsonSerialize}. 291 */ 292 public abstract static class None 293 extends JsonSerializer<Object> { } 294 } 295