1 package com.fasterxml.jackson.databind.deser.std;
2
3 import java.io.IOException;
4 import java.util.Collection;
5
6 import com.fasterxml.jackson.annotation.JsonFormat;
7 import com.fasterxml.jackson.core.*;
8 import com.fasterxml.jackson.databind.*;
9 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
10 import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
11 import com.fasterxml.jackson.databind.deser.NullValueProvider;
12 import com.fasterxml.jackson.databind.deser.ValueInstantiator;
13 import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams;
14 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
15
16
21 @JacksonStdImpl
22 public final class StringCollectionDeserializer
23 extends ContainerDeserializerBase<Collection<String>>
24 implements ContextualDeserializer
25 {
26 private static final long serialVersionUID = 1L;
27
28
29
30
34 protected final JsonDeserializer<String> _valueDeserializer;
35
36
37
38
41 protected final ValueInstantiator _valueInstantiator;
42
43
47 protected final JsonDeserializer<Object> _delegateDeserializer;
48
49
50
51
56
57 public StringCollectionDeserializer(JavaType collectionType,
58 JsonDeserializer<?> valueDeser, ValueInstantiator valueInstantiator)
59 {
60 this(collectionType, valueInstantiator, null, valueDeser, valueDeser, null);
61 }
62
63 @SuppressWarnings("unchecked")
64 protected StringCollectionDeserializer(JavaType collectionType,
65 ValueInstantiator valueInstantiator, JsonDeserializer<?> delegateDeser,
66 JsonDeserializer<?> valueDeser,
67 NullValueProvider nuller, Boolean unwrapSingle)
68 {
69 super(collectionType, nuller, unwrapSingle);
70 _valueDeserializer = (JsonDeserializer<String>) valueDeser;
71 _valueInstantiator = valueInstantiator;
72 _delegateDeserializer = (JsonDeserializer<Object>) delegateDeser;
73 }
74
75 protected StringCollectionDeserializer withResolved(JsonDeserializer<?> delegateDeser,
76 JsonDeserializer<?> valueDeser,
77 NullValueProvider nuller, Boolean unwrapSingle)
78 {
79 if ((_unwrapSingle == unwrapSingle) && (_nullProvider == nuller)
80 && (_valueDeserializer == valueDeser) && (_delegateDeserializer == delegateDeser)) {
81 return this;
82 }
83 return new StringCollectionDeserializer(_containerType, _valueInstantiator,
84 delegateDeser, valueDeser, nuller, unwrapSingle);
85 }
86
87 @Override
88 public boolean isCachable() {
89
90
91 return (_valueDeserializer == null) && (_delegateDeserializer == null);
92 }
93
94
99 @Override
100 public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
101 BeanProperty property) throws JsonMappingException
102 {
103
104 JsonDeserializer<Object> delegate = null;
105 if (_valueInstantiator != null) {
106
107 AnnotatedWithParams delegateCreator = _valueInstantiator.getArrayDelegateCreator();
108 if (delegateCreator != null) {
109 JavaType delegateType = _valueInstantiator.getArrayDelegateType(ctxt.getConfig());
110 delegate = findDeserializer(ctxt, delegateType, property);
111 } else if ((delegateCreator = _valueInstantiator.getDelegateCreator()) != null) {
112 JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig());
113 delegate = findDeserializer(ctxt, delegateType, property);
114 }
115 }
116 JsonDeserializer<?> valueDeser = _valueDeserializer;
117 final JavaType valueType = _containerType.getContentType();
118 if (valueDeser == null) {
119
120 valueDeser = findConvertingContentDeserializer(ctxt, property, valueDeser);
121 if (valueDeser == null) {
122
123 valueDeser = ctxt.findContextualValueDeserializer(valueType, property);
124 }
125 } else {
126 valueDeser = ctxt.handleSecondaryContextualization(valueDeser, property, valueType);
127 }
128
129
130 Boolean unwrapSingle = findFormatFeature(ctxt, property, Collection.class,
131 JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
132 NullValueProvider nuller = findContentNullProvider(ctxt, property, valueDeser);
133 if (isDefaultDeserializer(valueDeser)) {
134 valueDeser = null;
135 }
136 return withResolved(delegate, valueDeser, nuller, unwrapSingle);
137 }
138
139
144
145 @SuppressWarnings("unchecked")
146 @Override
147 public JsonDeserializer<Object> getContentDeserializer() {
148 JsonDeserializer<?> deser = _valueDeserializer;
149 return (JsonDeserializer<Object>) deser;
150 }
151
152 @Override
153 public ValueInstantiator getValueInstantiator() {
154 return _valueInstantiator;
155 }
156
157
162
163 @SuppressWarnings("unchecked")
164 @Override
165 public Collection<String> deserialize(JsonParser p, DeserializationContext ctxt)
166 throws IOException
167 {
168 if (_delegateDeserializer != null) {
169 return (Collection<String>) _valueInstantiator.createUsingDelegate(ctxt,
170 _delegateDeserializer.deserialize(p, ctxt));
171 }
172 final Collection<String> result = (Collection<String>) _valueInstantiator.createUsingDefault(ctxt);
173 return deserialize(p, ctxt, result);
174 }
175
176 @Override
177 public Collection<String> deserialize(JsonParser p, DeserializationContext ctxt,
178 Collection<String> result)
179 throws IOException
180 {
181
182 if (!p.isExpectedStartArrayToken()) {
183 return handleNonArray(p, ctxt, result);
184 }
185
186 if (_valueDeserializer != null) {
187 return deserializeUsingCustom(p, ctxt, result, _valueDeserializer);
188 }
189 try {
190 while (true) {
191
192 String value = p.nextTextValue();
193 if (value != null) {
194 result.add(value);
195 continue;
196 }
197 JsonToken t = p.getCurrentToken();
198 if (t == JsonToken.END_ARRAY) {
199 break;
200 }
201 if (t == JsonToken.VALUE_NULL) {
202 if (_skipNullValues) {
203 continue;
204 }
205 value = (String) _nullProvider.getNullValue(ctxt);
206 } else {
207 value = _parseString(p, ctxt);
208 }
209 result.add(value);
210 }
211 } catch (Exception e) {
212 throw JsonMappingException.wrapWithPath(e, result, result.size());
213 }
214 return result;
215 }
216
217 private Collection<String> deserializeUsingCustom(JsonParser p, DeserializationContext ctxt,
218 Collection<String> result, final JsonDeserializer<String> deser) throws IOException
219 {
220 try {
221 while (true) {
222
227 String value;
228 if (p.nextTextValue() == null) {
229 JsonToken t = p.getCurrentToken();
230 if (t == JsonToken.END_ARRAY) {
231 break;
232 }
233
234 if (t == JsonToken.VALUE_NULL) {
235 if (_skipNullValues) {
236 continue;
237 }
238 value = (String) _nullProvider.getNullValue(ctxt);
239 } else {
240 value = deser.deserialize(p, ctxt);
241 }
242 } else {
243 value = deser.deserialize(p, ctxt);
244 }
245 result.add(value);
246 }
247 } catch (Exception e) {
248 throw JsonMappingException.wrapWithPath(e, result, result.size());
249 }
250 return result;
251 }
252
253 @Override
254 public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
255 TypeDeserializer typeDeserializer) throws IOException {
256
257 return typeDeserializer.deserializeTypedFromArray(p, ctxt);
258 }
259
260
265 @SuppressWarnings("unchecked")
266 private final Collection<String> handleNonArray(JsonParser p, DeserializationContext ctxt,
267 Collection<String> result) throws IOException
268 {
269
270 boolean canWrap = (_unwrapSingle == Boolean.TRUE) ||
271 ((_unwrapSingle == null) &&
272 ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
273 if (!canWrap) {
274 return (Collection<String>) ctxt.handleUnexpectedToken(_containerType.getRawClass(), p);
275 }
276
277 JsonDeserializer<String> valueDes = _valueDeserializer;
278 JsonToken t = p.getCurrentToken();
279
280 String value;
281
282 if (t == JsonToken.VALUE_NULL) {
283
284 if (_skipNullValues) {
285 return result;
286 }
287 value = (String) _nullProvider.getNullValue(ctxt);
288 } else {
289 try {
290 value = (valueDes == null) ? _parseString(p, ctxt) : valueDes.deserialize(p, ctxt);
291 } catch (Exception e) {
292 throw JsonMappingException.wrapWithPath(e, result, result.size());
293 }
294 }
295 result.add(value);
296 return result;
297 }
298 }
299