1 package com.fasterxml.jackson.databind.ser.impl;
2
3 import java.io.IOException;
4 import java.util.*;
5
6 import com.fasterxml.jackson.core.JsonGenerator;
7 import com.fasterxml.jackson.databind.*;
8 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
9 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
10 import com.fasterxml.jackson.databind.ser.ContainerSerializer;
11 import com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase;
12
13 /**
14  * This is an optimized serializer for Lists that can be efficiently
15  * traversed by index (as opposed to others, such as {@link LinkedList}
16  * that cannot}.
17  */

18 @JacksonStdImpl
19 public final class IndexedListSerializer
20     extends AsArraySerializerBase<List<?>>
21 {
22     private static final long serialVersionUID = 1L;
23
24     public IndexedListSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts,
25             JsonSerializer<Object> valueSerializer)
26     {
27         super(List.class, elemType, staticTyping, vts, valueSerializer);
28     }
29
30     public IndexedListSerializer(IndexedListSerializer src,
31             BeanProperty property, TypeSerializer vts, JsonSerializer<?> valueSerializer,
32             Boolean unwrapSingle) {
33         super(src, property, vts, valueSerializer, unwrapSingle);
34     }
35
36     @Override
37     public IndexedListSerializer withResolved(BeanProperty property,
38             TypeSerializer vts, JsonSerializer<?> elementSerializer,
39             Boolean unwrapSingle) {
40         return new IndexedListSerializer(this, property, vts, elementSerializer, unwrapSingle);
41     }
42
43     /*
44     /**********************************************************
45     /* Accessors
46     /**********************************************************
47      */

48     
49     @Override
50     public boolean isEmpty(SerializerProvider prov, List<?> value) {
51         return value.isEmpty();
52     }
53
54     @Override
55     public boolean hasSingleElement(List<?> value) {
56         return (value.size() == 1);
57     }
58
59     @Override
60     public ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts) {
61         return new IndexedListSerializer(this
62                 _property, vts, _elementSerializer, _unwrapSingle);
63     }
64
65     @Override
66     public final void serialize(List<?> value, JsonGenerator gen, SerializerProvider provider)
67         throws IOException
68     {
69         final int len = value.size();
70         if (len == 1) {
71             if (((_unwrapSingle == null) &&
72                     provider.isEnabled(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED))
73                     || (_unwrapSingle == Boolean.TRUE)) {
74                 serializeContents(value, gen, provider);
75                 return;
76             }
77         }
78         gen.writeStartArray(value, len);
79         serializeContents(value, gen, provider);
80         gen.writeEndArray();
81     }
82     
83     @Override
84     public void serializeContents(List<?> value, JsonGenerator g, SerializerProvider provider)
85         throws IOException
86     {
87         if (_elementSerializer != null) {
88             serializeContentsUsing(value, g, provider, _elementSerializer);
89             return;
90         }
91         if (_valueTypeSerializer != null) {
92             serializeTypedContents(value, g, provider);
93             return;
94         }
95         final int len = value.size();
96         if (len == 0) {
97             return;
98         }
99         int i = 0;
100         try {
101             PropertySerializerMap serializers = _dynamicSerializers;
102             for (; i < len; ++i) {
103                 Object elem = value.get(i);
104                 if (elem == null) {
105                     provider.defaultSerializeNull(g);
106                 } else {
107                     Class<?> cc = elem.getClass();
108                     JsonSerializer<Object> serializer = serializers.serializerFor(cc);
109                     if (serializer == null) {
110                         // To fix [JACKSON-508]
111                         if (_elementType.hasGenericTypes()) {
112                             serializer = _findAndAddDynamic(serializers,
113                                     provider.constructSpecializedType(_elementType, cc), provider);
114                         } else {
115                             serializer = _findAndAddDynamic(serializers, cc, provider);
116                         }
117                         serializers = _dynamicSerializers;
118                     }
119                     serializer.serialize(elem, g, provider);
120                 }
121             }
122         } catch (Exception e) {
123             wrapAndThrow(provider, e, value, i);
124         }
125     }
126     
127     public void serializeContentsUsing(List<?> value, JsonGenerator jgen, SerializerProvider provider,
128             JsonSerializer<Object> ser)
129         throws IOException
130     {
131         final int len = value.size();
132         if (len == 0) {
133             return;
134         }
135         final TypeSerializer typeSer = _valueTypeSerializer;
136         for (int i = 0; i < len; ++i) {
137             Object elem = value.get(i);
138             try {
139                 if (elem == null) {
140                     provider.defaultSerializeNull(jgen);
141                 } else if (typeSer == null) {
142                     ser.serialize(elem, jgen, provider);
143                 } else {
144                     ser.serializeWithType(elem, jgen, provider, typeSer);
145                 }
146             } catch (Exception e) {
147                 // [JACKSON-55] Need to add reference information
148                 wrapAndThrow(provider, e, value, i);
149             }
150         }
151     }
152
153     public void serializeTypedContents(List<?> value, JsonGenerator jgen, SerializerProvider provider)
154         throws IOException
155     {
156         final int len = value.size();
157         if (len == 0) {
158             return;
159         }
160         int i = 0;
161         try {
162             final TypeSerializer typeSer = _valueTypeSerializer;
163             PropertySerializerMap serializers = _dynamicSerializers;
164             for (; i < len; ++i) {
165                 Object elem = value.get(i);
166                 if (elem == null) {
167                     provider.defaultSerializeNull(jgen);
168                 } else {
169                     Class<?> cc = elem.getClass();
170                     JsonSerializer<Object> serializer = serializers.serializerFor(cc);
171                     if (serializer == null) {
172                         // To fix [JACKSON-508]
173                         if (_elementType.hasGenericTypes()) {
174                             serializer = _findAndAddDynamic(serializers,
175                                     provider.constructSpecializedType(_elementType, cc), provider);
176                         } else {
177                             serializer = _findAndAddDynamic(serializers, cc, provider);
178                         }
179                         serializers = _dynamicSerializers;
180                     }
181                     serializer.serializeWithType(elem, jgen, provider, typeSer);
182                 }
183             }
184         } catch (Exception e) {
185             wrapAndThrow(provider, e, value, i);
186         }
187     }
188 }
189