1 package com.fasterxml.jackson.databind.ser.std;
2
3 import java.io.IOException;
4 import java.util.Collection;
5 import java.util.Iterator;
6
7 import com.fasterxml.jackson.core.*;
8
9 import com.fasterxml.jackson.databind.BeanProperty;
10 import com.fasterxml.jackson.databind.JavaType;
11 import com.fasterxml.jackson.databind.JsonSerializer;
12 import com.fasterxml.jackson.databind.SerializationFeature;
13 import com.fasterxml.jackson.databind.SerializerProvider;
14 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
15 import com.fasterxml.jackson.databind.ser.ContainerSerializer;
16 import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
17
18 /**
19  * Fallback serializer for cases where Collection is not known to be
20  * of type for which more specializer serializer exists (such as
21  * index-accessible List).
22  * If so, we will just construct an {@link java.util.Iterator}
23  * to iterate over elements.
24  */

25 public class CollectionSerializer
26     extends AsArraySerializerBase<Collection<?>>
27 {
28     private static final long serialVersionUID = 1L;
29
30     /*
31     /**********************************************************
32     /* Life-cycle
33     /**********************************************************
34      */

35
36     /**
37      * @since 2.6
38      */

39     public CollectionSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts,
40             JsonSerializer<Object> valueSerializer) {
41         super(Collection.class, elemType, staticTyping, vts, valueSerializer);
42     }
43
44     /**
45      * @deprecated since 2.6
46      */

47     @Deprecated // since 2.6
48     public CollectionSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts,
49             BeanProperty property, JsonSerializer<Object> valueSerializer) {
50         // note: assumption is 'property' is always passed as null
51         this(elemType, staticTyping, vts, valueSerializer);
52     }
53     
54     public CollectionSerializer(CollectionSerializer src,
55             BeanProperty property, TypeSerializer vts, JsonSerializer<?> valueSerializer,
56             Boolean unwrapSingle) {
57         super(src, property, vts, valueSerializer, unwrapSingle);
58     }
59     
60     @Override
61     public ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts) {
62         return new CollectionSerializer(this, _property, vts, _elementSerializer, _unwrapSingle);
63     }
64
65     @Override
66     public CollectionSerializer withResolved(BeanProperty property,
67             TypeSerializer vts, JsonSerializer<?> elementSerializer,
68             Boolean unwrapSingle) {
69         return new CollectionSerializer(this, property, vts, elementSerializer, unwrapSingle);
70     }
71
72     /*
73     /**********************************************************
74     /* Accessors
75     /**********************************************************
76      */

77
78     @Override
79     public boolean isEmpty(SerializerProvider prov, Collection<?> value) {
80         return value.isEmpty();
81     }
82
83     @Override
84     public boolean hasSingleElement(Collection<?> value) {
85         return value.size() == 1;
86     }
87
88     /*
89     /**********************************************************
90     /* Actual serialization
91     /**********************************************************
92      */

93
94     @Override
95     public final void serialize(Collection<?> value, JsonGenerator g, SerializerProvider provider) throws IOException
96     {
97         final int len = value.size();
98         if (len == 1) {
99             if (((_unwrapSingle == null) &&
100                     provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED))
101                     || (_unwrapSingle == Boolean.TRUE)) {
102                 serializeContents(value, g, provider);
103                 return;
104             }
105         }
106         g.writeStartArray(value, len);
107         serializeContents(value, g, provider);
108         g.writeEndArray();
109     }
110     
111     @Override
112     public void serializeContents(Collection<?> value, JsonGenerator g, SerializerProvider provider) throws IOException
113     {
114         g.setCurrentValue(value);
115         if (_elementSerializer != null) {
116             serializeContentsUsing(value, g, provider, _elementSerializer);
117             return;
118         }
119         Iterator<?> it = value.iterator();
120         if (!it.hasNext()) {
121             return;
122         }
123         PropertySerializerMap serializers = _dynamicSerializers;
124         final TypeSerializer typeSer = _valueTypeSerializer;
125
126         int i = 0;
127         try {
128             do {
129                 Object elem = it.next();
130                 if (elem == null) {
131                     provider.defaultSerializeNull(g);
132                 } else {
133                     Class<?> cc = elem.getClass();
134                     JsonSerializer<Object> serializer = serializers.serializerFor(cc);
135                     if (serializer == null) {
136                         if (_elementType.hasGenericTypes()) {
137                             serializer = _findAndAddDynamic(serializers,
138                                     provider.constructSpecializedType(_elementType, cc), provider);
139                         } else {
140                             serializer = _findAndAddDynamic(serializers, cc, provider);
141                         }
142                         serializers = _dynamicSerializers;
143                     }
144                     if (typeSer == null) {
145                         serializer.serialize(elem, g, provider);
146                     } else {
147                         serializer.serializeWithType(elem, g, provider, typeSer);
148                     }
149                 }
150                 ++i;
151             } while (it.hasNext());
152         } catch (Exception e) {
153             wrapAndThrow(provider, e, value, i);
154         }
155     }
156
157     public void serializeContentsUsing(Collection<?> value, JsonGenerator g, SerializerProvider provider,
158             JsonSerializer<Object> ser) throws IOException
159     {
160         Iterator<?> it = value.iterator();
161         if (it.hasNext()) {
162             TypeSerializer typeSer = _valueTypeSerializer;
163             int i = 0;
164             do {
165                 Object elem = it.next();
166                 try {
167                     if (elem == null) {
168                         provider.defaultSerializeNull(g);
169                     } else {
170                         if (typeSer == null) {
171                             ser.serialize(elem, g, provider);
172                         } else {
173                             ser.serializeWithType(elem, g, provider, typeSer);
174                         }
175                     }
176                     ++i;
177                 } catch (Exception e) {
178                     wrapAndThrow(provider, e, value, i);
179                 }
180             } while (it.hasNext());
181         }
182     }
183 }
184