1 package com.fasterxml.jackson.databind.seq;
2 
3 import java.io.*;
4 import java.util.*;
5 
6 import com.fasterxml.jackson.core.*;
7 import com.fasterxml.jackson.core.type.TypeReference;
8 
9 import com.fasterxml.jackson.databind.BaseMapTest;
10 import com.fasterxml.jackson.databind.MappingIterator;
11 import com.fasterxml.jackson.databind.ObjectMapper;
12 import com.fasterxml.jackson.databind.ObjectReader;
13 
14 @SuppressWarnings("resource")
15 public class ReadValuesTest extends BaseMapTest
16 {
17     static class Bean {
18         public int a;
19 
20         @Override
equals(Object o)21         public boolean equals(Object o) {
22             if (o == null || o.getClass() != getClass()) return false;
23             Bean other = (Bean) o;
24             return other.a == this.a;
25         }
hashCode()26         @Override public int hashCode() { return a; }
27     }
28 
29     /*
30     /**********************************************************
31     /* Unit tests; root-level value sequences via Mapper
32     /**********************************************************
33      */
34 
35     private enum Source {
36         STRING,
37         INPUT_STREAM,
38         READER,
39         BYTE_ARRAY,
40         BYTE_ARRAY_OFFSET
41         ;
42     }
43 
44     private final ObjectMapper MAPPER = new ObjectMapper();
45 
testRootBeans()46     public void testRootBeans() throws Exception
47     {
48         for (Source src : Source.values()) {
49             _testRootBeans(src);
50         }
51     }
52 
_iterator(ObjectReader r, String json, Source srcType)53     private <T> MappingIterator<T> _iterator(ObjectReader r,
54             String json,
55             Source srcType) throws IOException
56     {
57         switch (srcType) {
58         case BYTE_ARRAY:
59             return r.readValues(json.getBytes("UTF-8"));
60         case BYTE_ARRAY_OFFSET:
61             {
62                 ByteArrayOutputStream out = new ByteArrayOutputStream();
63                 out.write(0);
64                 out.write(0);
65                 out.write(0);
66                 out.write(json.getBytes("UTF-8"));
67                 out.write(0);
68                 out.write(0);
69                 out.write(0);
70                 byte[] b = out.toByteArray();
71                 return r.readValues(b, 3, b.length-6);
72             }
73         case INPUT_STREAM:
74             return r.readValues(new ByteArrayInputStream(json.getBytes("UTF-8")));
75         case READER:
76             return r.readValues(new StringReader(json));
77         case STRING:
78         default:
79             return r.readValues(json);
80         }
81     }
82 
_testRootBeans(Source srcType)83     private void _testRootBeans(Source srcType) throws Exception
84     {
85         final String JSON = "{\"a\":3}{\"a\":27}  ";
86 
87         MappingIterator<Bean> it = _iterator(MAPPER.readerFor(Bean.class),
88                 JSON, srcType);
89         assertNotNull(it.getCurrentLocation());
90         assertTrue(it.hasNext());
91         Bean b = it.next();
92         assertEquals(3, b.a);
93         assertTrue(it.hasNext());
94         b = it.next();
95         assertEquals(27, b.a);
96         assertFalse(it.hasNext());
97         it.close();
98 
99         // Also, test 'readAll()'
100         it = _iterator(MAPPER.readerFor(Bean.class), JSON, srcType);
101         List<Bean> all = it.readAll();
102         assertEquals(2, all.size());
103         it.close();
104 
105         it = _iterator(MAPPER.readerFor(Bean.class), "{\"a\":3}{\"a\":3}", srcType);
106         Set<Bean> set = it.readAll(new HashSet<Bean>());
107         assertEquals(HashSet.class, set.getClass());
108         assertEquals(1, set.size());
109         assertEquals(3, set.iterator().next().a);
110         it.close();
111     }
112 
testRootBeansInArray()113     public void testRootBeansInArray() throws Exception
114     {
115         final String JSON = "[{\"a\":6}, {\"a\":-7}]";
116 
117         MappingIterator<Bean> it = MAPPER.readerFor(Bean.class).readValues(JSON);
118 
119         assertNotNull(it.getCurrentLocation());
120         assertTrue(it.hasNext());
121         Bean b = it.next();
122         assertEquals(6, b.a);
123         assertTrue(it.hasNext());
124         b = it.next();
125         assertEquals(-7, b.a);
126         assertFalse(it.hasNext());
127         it.close();
128 
129         // Also, test 'readAll()'
130         it = MAPPER.readerFor(Bean.class).readValues(JSON);
131         List<Bean> all = it.readAll();
132         assertEquals(2, all.size());
133         it.close();
134 
135         it = MAPPER.readerFor(Bean.class).readValues("[{\"a\":4},{\"a\":4}]");
136         Set<Bean> set = it.readAll(new HashSet<Bean>());
137         assertEquals(HashSet.class, set.getClass());
138         assertEquals(1, set.size());
139         assertEquals(4, set.iterator().next().a);
140     }
141 
testRootMaps()142     public void testRootMaps() throws Exception
143     {
144         final String JSON = "{\"a\":3}{\"a\":27}  ";
145         Iterator<Map<?,?>> it = MAPPER.readerFor(Map.class).readValues(JSON);
146 
147         assertNotNull(((MappingIterator<?>) it).getCurrentLocation());
148         assertTrue(it.hasNext());
149         Map<?,?> map = it.next();
150         assertEquals(1, map.size());
151         assertEquals(Integer.valueOf(3), map.get("a"));
152         assertTrue(it.hasNext());
153         assertNotNull(((MappingIterator<?>) it).getCurrentLocation());
154         map = it.next();
155         assertEquals(1, map.size());
156         assertEquals(Integer.valueOf(27), map.get("a"));
157         assertFalse(it.hasNext());
158     }
159 
160     /*
161     /**********************************************************
162     /* Unit tests; root-level value sequences via JsonParser
163     /**********************************************************
164      */
165 
testRootBeansWithParser()166     public void testRootBeansWithParser() throws Exception
167     {
168         final String JSON = "{\"a\":3}{\"a\":27}  ";
169         JsonParser jp = MAPPER.createParser(JSON);
170 
171         Iterator<Bean> it = jp.readValuesAs(Bean.class);
172 
173         assertTrue(it.hasNext());
174         Bean b = it.next();
175         assertEquals(3, b.a);
176         assertTrue(it.hasNext());
177         b = it.next();
178         assertEquals(27, b.a);
179         assertFalse(it.hasNext());
180     }
181 
testRootArraysWithParser()182     public void testRootArraysWithParser() throws Exception
183     {
184         final String JSON = "[1][3]";
185         JsonParser jp = MAPPER.createParser(JSON);
186 
187         // NOTE: We must point JsonParser to the first element; if we tried to
188         // use "managed" accessor, it would try to advance past START_ARRAY.
189         assertToken(JsonToken.START_ARRAY, jp.nextToken());
190 
191         Iterator<int[]> it = MAPPER.readerFor(int[].class).readValues(jp);
192         assertTrue(it.hasNext());
193         int[] array = it.next();
194         assertEquals(1, array.length);
195         assertEquals(1, array[0]);
196         assertTrue(it.hasNext());
197         array = it.next();
198         assertEquals(1, array.length);
199         assertEquals(3, array[0]);
200         assertFalse(it.hasNext());
201     }
202 
testHasNextWithEndArray()203     public void testHasNextWithEndArray() throws Exception {
204         final String JSON = "[1,3]";
205         JsonParser jp = MAPPER.createParser(JSON);
206 
207         // NOTE: We must point JsonParser to the first element; if we tried to
208         // use "managed" accessor, it would try to advance past START_ARRAY.
209         assertToken(JsonToken.START_ARRAY, jp.nextToken());
210         jp.nextToken();
211 
212         Iterator<Integer> it = MAPPER.readerFor(Integer.class).readValues(jp);
213         assertTrue(it.hasNext());
214         int value = it.next();
215         assertEquals(1, value);
216         assertTrue(it.hasNext());
217         value = it.next();
218         assertEquals(3, value);
219         assertFalse(it.hasNext());
220         assertFalse(it.hasNext());
221     }
222 
testHasNextWithEndArrayManagedParser()223     public void testHasNextWithEndArrayManagedParser() throws Exception {
224         final String JSON = "[1,3]";
225 
226         Iterator<Integer> it = MAPPER.readerFor(Integer.class).readValues(JSON);
227         assertTrue(it.hasNext());
228         int value = it.next();
229         assertEquals(1, value);
230         assertTrue(it.hasNext());
231         value = it.next();
232         assertEquals(3, value);
233         assertFalse(it.hasNext());
234         assertFalse(it.hasNext());
235     }
236 
237     /*
238     /**********************************************************
239     /* Unit tests; non-root arrays
240     /**********************************************************
241      */
242 
testNonRootBeans()243     public void testNonRootBeans() throws Exception
244     {
245         final String JSON = "{\"leaf\":[{\"a\":3},{\"a\":27}]}";
246         JsonParser jp = MAPPER.createParser(JSON);
247         assertToken(JsonToken.START_OBJECT, jp.nextToken());
248         assertToken(JsonToken.FIELD_NAME, jp.nextToken());
249         assertToken(JsonToken.START_ARRAY, jp.nextToken());
250         // can either advance to first START_OBJECT, or clear current token;
251         // explicitly passed JsonParser MUST point to the first token of
252         // the first element
253         assertToken(JsonToken.START_OBJECT, jp.nextToken());
254 
255         Iterator<Bean> it = MAPPER.readerFor(Bean.class).readValues(jp);
256 
257         assertTrue(it.hasNext());
258         Bean b = it.next();
259         assertEquals(3, b.a);
260         assertTrue(it.hasNext());
261         b = it.next();
262         assertEquals(27, b.a);
263         assertFalse(it.hasNext());
264         jp.close();
265     }
266 
testNonRootMapsWithParser()267     public void testNonRootMapsWithParser() throws Exception
268     {
269         final String JSON = "[{\"a\":3},{\"a\":27}]";
270         JsonParser jp = MAPPER.createParser(JSON);
271         assertToken(JsonToken.START_ARRAY, jp.nextToken());
272 
273         // can either advance to first START_OBJECT, or clear current token;
274         // explicitly passed JsonParser MUST point to the first token of
275         // the first element
276         jp.clearCurrentToken();
277 
278         Iterator<Map<?,?>> it = MAPPER.readerFor(Map.class).readValues(jp);
279 
280         assertTrue(it.hasNext());
281         Map<?,?> map = it.next();
282         assertEquals(1, map.size());
283         assertEquals(Integer.valueOf(3), map.get("a"));
284         assertTrue(it.hasNext());
285         map = it.next();
286         assertEquals(1, map.size());
287         assertEquals(Integer.valueOf(27), map.get("a"));
288         assertFalse(it.hasNext());
289         jp.close();
290     }
291 
testNonRootMapsWithObjectReader()292     public void testNonRootMapsWithObjectReader() throws Exception
293     {
294         String JSON = "[{ \"hi\": \"ho\", \"neighbor\": \"Joe\" },\n"
295             +"{\"boy\": \"howdy\", \"huh\": \"what\"}]";
296         final MappingIterator<Map<String, Object>> iterator = MAPPER
297                 .reader()
298                 .forType(new TypeReference<Map<String, Object>>(){})
299                 .readValues(JSON);
300 
301         Map<String,Object> map;
302         assertTrue(iterator.hasNext());
303         map = iterator.nextValue();
304         assertEquals(2, map.size());
305         assertTrue(iterator.hasNext());
306         map = iterator.nextValue();
307         assertEquals(2, map.size());
308         assertFalse(iterator.hasNext());
309     }
310 
testNonRootArraysUsingParser()311     public void testNonRootArraysUsingParser() throws Exception
312     {
313         final String JSON = "[[1],[3]]";
314         JsonParser p = MAPPER.createParser(JSON);
315         assertToken(JsonToken.START_ARRAY, p.nextToken());
316 
317         // Important: as of 2.1, START_ARRAY can only be skipped if the
318         // target type is NOT a Collection or array Java type.
319         // So we have to explicitly skip it in this particular case.
320         assertToken(JsonToken.START_ARRAY, p.nextToken());
321 
322         Iterator<int[]> it = MAPPER.readValues(p, int[].class);
323 
324         assertTrue(it.hasNext());
325         int[] array = it.next();
326         assertEquals(1, array.length);
327         assertEquals(1, array[0]);
328         assertTrue(it.hasNext());
329         array = it.next();
330         assertEquals(1, array.length);
331         assertEquals(3, array[0]);
332         assertFalse(it.hasNext());
333         p.close();
334     }
335 
testEmptyIterator()336     public void testEmptyIterator() throws Exception
337     {
338         MappingIterator<Object> empty = MappingIterator.emptyIterator();
339 
340         assertFalse(empty.hasNext());
341         assertFalse(empty.hasNextValue());
342 
343         empty.close();
344     }
345 }
346