• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.seq;
2 
3 import java.io.Closeable;
4 import java.io.IOException;
5 import java.io.StringWriter;
6 import java.util.*;
7 
8 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
9 import com.fasterxml.jackson.annotation.JsonTypeInfo;
10 import com.fasterxml.jackson.annotation.JsonTypeName;
11 
12 import com.fasterxml.jackson.core.JsonGenerator;
13 import com.fasterxml.jackson.core.io.SerializedString;
14 
15 import com.fasterxml.jackson.databind.*;
16 import com.fasterxml.jackson.databind.json.JsonMapper;
17 
18 public class SequenceWriterTest extends BaseMapTest
19 {
20     static class Bean {
21         public int a;
22 
Bean(int value)23         public Bean(int value) { a = value; }
24 
25         @Override
equals(Object o)26         public boolean equals(Object o) {
27             if (o == null || o.getClass() != getClass()) return false;
28             Bean other = (Bean) o;
29             return other.a == this.a;
30         }
hashCode()31         @Override public int hashCode() { return a; }
32     }
33 
34     @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
35     static class PolyBase {
36     }
37 
38     @JsonTypeName("A")
39     static class ImplA extends PolyBase {
40         public int value;
41 
ImplA(int v)42         public ImplA(int v) { value = v; }
43     }
44 
45     @JsonTypeName("B")
46     static class ImplB extends PolyBase {
47         public int b;
48 
ImplB(int v)49         public ImplB(int v) { b = v; }
50     }
51 
52     static class BareBase {
53         public int a = 1;
54     }
55 
56     @JsonPropertyOrder({ "a", "b" })
57     static class BareBaseExt extends BareBase {
58         public int b = 2;
59     }
60 
61     static class BareBaseCloseable extends BareBase
62         implements Closeable
63     {
64         public int c = 3;
65 
66         boolean closed = false;
67 
68         @Override
close()69         public void close() throws IOException {
70             closed = true;
71         }
72     }
73 
74     static class CloseableValue implements Closeable
75     {
76         public int x;
77 
78         public boolean closed;
79 
80         @Override
close()81         public void close() throws IOException {
82             closed = true;
83         }
84     }
85 
86     /*
87     /**********************************************************
88     /* Test methods, simple writes
89     /**********************************************************
90      */
91 
92     private final ObjectMapper MAPPER = new ObjectMapper();
93     private final ObjectWriter WRITER = MAPPER.writer()
94             .withRootValueSeparator("\n");
95 
testSimpleNonArray()96     public void testSimpleNonArray() throws Exception
97     {
98         StringWriter strw = new StringWriter();
99         SequenceWriter w = WRITER
100                 .forType(Bean.class)
101                 .writeValues(strw);
102         w.write(new Bean(13))
103             .write(new Bean(-6))
104             .writeAll(new Bean[] { new Bean(3), new Bean(1) })
105             .writeAll(Arrays.asList(new Bean(5), new Bean(7)))
106         ;
107         w.close();
108         assertEquals(aposToQuotes("{'a':13}\n{'a':-6}\n{'a':3}\n{'a':1}\n{'a':5}\n{'a':7}"),
109                 strw.toString());
110 
111         strw = new StringWriter();
112         JsonGenerator gen = WRITER.createGenerator(strw);
113         w = WRITER
114                 .withRootValueSeparator(new SerializedString("/"))
115                 .writeValues(gen);
116         w.write(new Bean(1))
117             .write(new Bean(2));
118         w.close();
119         gen.close();
120         assertEquals(aposToQuotes("{'a':1}/{'a':2}"),
121                 strw.toString());
122     }
123 
testSimpleArray()124     public void testSimpleArray() throws Exception
125     {
126         StringWriter strw = new StringWriter();
127         SequenceWriter w = WRITER.writeValuesAsArray(strw);
128         w.write(new Bean(1))
129             .write(new Bean(2))
130             .writeAll(new Bean[] { new Bean(-7), new Bean(2) });
131         w.close();
132         assertEquals(aposToQuotes("[{'a':1},{'a':2},{'a':-7},{'a':2}]"),
133                 strw.toString());
134 
135         strw = new StringWriter();
136         JsonGenerator gen = WRITER.createGenerator(strw);
137         w = WRITER.writeValuesAsArray(gen);
138         Collection<Bean> bean = Collections.singleton(new Bean(3));
139         w.write(new Bean(1))
140             .write(null)
141             .writeAll((Iterable<Bean>) bean);
142         w.close();
143         gen.close();
144         assertEquals(aposToQuotes("[{'a':1},null,{'a':3}]"),
145                 strw.toString());
146     }
147 
148     /*
149     /**********************************************************
150     /* Test methods, polymorphic writes
151     /**********************************************************
152      */
153 
154     @SuppressWarnings("resource")
testPolymorphicNonArrayWithoutType()155     public void testPolymorphicNonArrayWithoutType() throws Exception
156     {
157         StringWriter strw = new StringWriter();
158         SequenceWriter w = WRITER
159                 .writeValues(strw);
160         w.write(new ImplA(3))
161             .write(new ImplA(4))
162             .close();
163         assertEquals(aposToQuotes("{'type':'A','value':3}\n{'type':'A','value':4}"),
164                 strw.toString());
165     }
166 
167     @SuppressWarnings("resource")
testPolymorphicArrayWithoutType()168     public void testPolymorphicArrayWithoutType() throws Exception
169     {
170         StringWriter strw = new StringWriter();
171         SequenceWriter w = WRITER
172                 .writeValuesAsArray(strw);
173         w.write(new ImplA(-1))
174             .write(new ImplA(6))
175             .close();
176         assertEquals(aposToQuotes("[{'type':'A','value':-1},{'type':'A','value':6}]"),
177                 strw.toString());
178     }
179 
testPolymorphicArrayWithType()180     public void testPolymorphicArrayWithType() throws Exception
181     {
182         StringWriter strw = new StringWriter();
183         SequenceWriter w = WRITER
184                 .forType(PolyBase.class)
185                 .writeValuesAsArray(strw);
186         w.write(new ImplA(-1))
187             .write(new ImplB(3))
188             .write(new ImplA(7));
189         w.flush();
190         w.close();
191         assertEquals(aposToQuotes("[{'type':'A','value':-1},{'type':'B','b':3},{'type':'A','value':7}]"),
192                 strw.toString());
193     }
194 
195     @SuppressWarnings("resource")
testSimpleCloseable()196     public void testSimpleCloseable() throws Exception
197     {
198         JsonMapper mapper = JsonMapper.builder().enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY).build();
199         ObjectWriter w = mapper.writer()
200                 .with(SerializationFeature.CLOSE_CLOSEABLE);
201         CloseableValue input = new CloseableValue();
202         assertFalse(input.closed);
203         StringWriter out = new StringWriter();
204         SequenceWriter seq = w.writeValues(out);
205         input = new CloseableValue();
206         assertFalse(input.closed);
207         seq.write(input);
208         assertTrue(input.closed);
209         seq.close();
210         input.close();
211         assertEquals(aposToQuotes("{'closed':false,'x':0}"), out.toString());
212     }
213 
testWithExplicitType()214     public void testWithExplicitType() throws Exception
215     {
216         ObjectWriter w = MAPPER.writer()
217                 // just for fun (and higher coverage):
218                 .without(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)
219                 .with(SerializationFeature.CLOSE_CLOSEABLE);
220         StringWriter out = new StringWriter();
221         SequenceWriter seq = w.writeValues(out);
222         // first full, as-is
223         seq.write(new BareBaseExt());
224         // but then just base type (no 'b' field)
225         seq.write(new BareBaseExt(), MAPPER.constructType(BareBase.class));
226 
227         // one more. And note! Check for Closeable is for _value_, not type
228         // so it's fine to expect closing here
229         BareBaseCloseable cl = new BareBaseCloseable();
230         seq.write(cl, MAPPER.constructType(BareBase.class));
231         assertTrue(cl.closed);
232         cl.close();
233 
234         seq.close();
235         seq.flush();
236         assertEquals(aposToQuotes("{'a':1,'b':2} {'a':1} {'a':1}"), out.toString());
237     }
238 }
239