• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind;
2 
3 import java.io.*;
4 import java.util.*;
5 
6 import com.fasterxml.jackson.annotation.JsonAnyGetter;
7 import com.fasterxml.jackson.annotation.JsonAnySetter;
8 import com.fasterxml.jackson.databind.type.TypeFactory;
9 import com.fasterxml.jackson.databind.util.LRUMap;
10 
11 /**
12  * Tests to verify that most core Jackson components can be serialized
13  * using default JDK serialization: this feature is useful for some
14  * platforms, such as Android, where memory management is handled
15  * much more aggressively.
16  */
17 public class TestJDKSerialization extends BaseMapTest
18 {
19     static class MyPojo {
20         public int x;
21         protected int y;
22 
MyPojo()23         public MyPojo() { }
MyPojo(int x0, int y0)24         public MyPojo(int x0, int y0) {
25             x = x0;
26             y = y0;
27         }
28 
getY()29         public int getY() { return y; }
setY(int y)30         public void setY(int y) { this.y = y; }
31     }
32 
33     // for [databind#899]
34     static class EnumPOJO {
35         public ABC abc = ABC.B;
36 
37         public Map<String,ABC> stuff = new LinkedHashMap<String,ABC>();
38     }
39 
40     static class AnyBean {
41         HashMap<String,Object> _map;
42 
AnyBean()43         public AnyBean() {
44             _map = new HashMap<String,Object>();
45         }
46 
47         @JsonAnySetter
addEntry(String key, Object value)48         AnyBean addEntry(String key, Object value) {
49             _map.put(key, value);
50             return this;
51         }
52 
53         @JsonAnyGetter
properties()54         public Map<String,Object> properties() {
55             return _map;
56         }
57     }
58 
59     /*
60     /**********************************************************
61     /* Tests for individual objects
62     /**********************************************************
63      */
64 
65     /* 18-Oct-2013, tatu: Not sure why, but looks like sharing the default
66      *   ObjectMapper here can lead to strange unit test suite failures, so
67      *   let's create a private copy for this class only.
68      */
69     private final ObjectMapper MAPPER = newJsonMapper();
70 
testConfigs()71     public void testConfigs() throws IOException
72     {
73         byte[] base = jdkSerialize(MAPPER.getDeserializationConfig().getBaseSettings());
74         assertNotNull(jdkDeserialize(base));
75 
76         // first things first: underlying BaseSettings
77 
78         DeserializationConfig origDC = MAPPER.getDeserializationConfig();
79         SerializationConfig origSC = MAPPER.getSerializationConfig();
80         byte[] dcBytes = jdkSerialize(origDC);
81         byte[] scBytes = jdkSerialize(origSC);
82 
83         DeserializationConfig dc = jdkDeserialize(dcBytes);
84         assertNotNull(dc);
85         assertEquals(dc._deserFeatures, origDC._deserFeatures);
86         SerializationConfig sc = jdkDeserialize(scBytes);
87         assertNotNull(sc);
88         assertEquals(sc._serFeatures, origSC._serFeatures);
89     }
90 
91     // for [databind#899]
testEnumHandlers()92     public void testEnumHandlers() throws IOException
93     {
94         ObjectMapper mapper = newJsonMapper();
95         // ensure we have serializers and/or deserializers, first
96         String json = mapper.writerFor(EnumPOJO.class)
97                 .writeValueAsString(new EnumPOJO());
98         EnumPOJO result = mapper.readerFor(EnumPOJO.class)
99                 .readValue(json);
100         assertNotNull(result);
101 
102         // and then use JDK serialization to freeze/thaw objects
103         byte[] bytes = jdkSerialize(mapper);
104         ObjectMapper mapper2 = jdkDeserialize(bytes);
105         assertNotNull(mapper2);
106 
107         bytes = jdkSerialize(mapper.readerFor(EnumPOJO.class));
108         ObjectReader r = jdkDeserialize(bytes);
109         assertNotNull(r);
110 
111         /* 14-Aug-2015, tatu: Looks like pre-loading JsonSerializer is problematic
112          *    at this point; comment out for now. Try to fix later on.
113          */
114         bytes = jdkSerialize(mapper.writerFor(EnumPOJO.class));
115         ObjectWriter w = jdkDeserialize(bytes);
116         assertNotNull(w);
117 
118         // plus, ensure objects are usable:
119         String json2 = w.writeValueAsString(new EnumPOJO());
120         assertEquals(json, json2);
121         EnumPOJO result2 = r.readValue(json2);
122         assertNotNull(result2);
123     }
124 
testObjectWriter()125     public void testObjectWriter() throws IOException
126     {
127         ObjectWriter origWriter = MAPPER.writer();
128         final String EXP_JSON = "{\"x\":2,\"y\":3}";
129         final MyPojo p = new MyPojo(2, 3);
130         assertEquals(EXP_JSON, origWriter.writeValueAsString(p));
131         String json = origWriter.writeValueAsString(new AnyBean()
132                 .addEntry("a", "b"));
133         assertNotNull(json);
134         byte[] bytes = jdkSerialize(origWriter);
135         ObjectWriter writer2 = jdkDeserialize(bytes);
136         assertEquals(EXP_JSON, writer2.writeValueAsString(p));
137     }
138 
testObjectReader()139     public void testObjectReader() throws IOException
140     {
141         ObjectReader origReader = MAPPER.readerFor(MyPojo.class);
142         String JSON = "{\"x\":1,\"y\":2}";
143         MyPojo p1 = origReader.readValue(JSON);
144         assertEquals(2, p1.y);
145         ObjectReader anyReader = MAPPER.readerFor(AnyBean.class);
146         AnyBean any = anyReader.readValue(JSON);
147         assertEquals(Integer.valueOf(2), any.properties().get("y"));
148 
149         byte[] readerBytes = jdkSerialize(origReader);
150         ObjectReader reader2 = jdkDeserialize(readerBytes);
151         MyPojo p2 = reader2.readValue(JSON);
152         assertEquals(2, p2.y);
153 
154         ObjectReader anyReader2 = jdkDeserialize(jdkSerialize(anyReader));
155         AnyBean any2 = anyReader2.readValue(JSON);
156         assertEquals(Integer.valueOf(2), any2.properties().get("y"));
157     }
158 
testObjectMapper()159     public void testObjectMapper() throws IOException
160     {
161         final String EXP_JSON = "{\"x\":2,\"y\":3}";
162         final MyPojo p = new MyPojo(2, 3);
163         assertEquals(EXP_JSON, MAPPER.writeValueAsString(p));
164         assertNotNull(MAPPER.getFactory());
165         assertNotNull(MAPPER.getFactory().getCodec());
166 
167         byte[] bytes = jdkSerialize(MAPPER);
168         ObjectMapper mapper2 = jdkDeserialize(bytes);
169         assertEquals(EXP_JSON, mapper2.writeValueAsString(p));
170         MyPojo p2 = mapper2.readValue(EXP_JSON, MyPojo.class);
171         assertEquals(p.x, p2.x);
172         assertEquals(p.y, p2.y);
173 
174         // [databind#2038]: verify that codec is not lost
175         assertNotNull(mapper2.getFactory());
176         assertNotNull(mapper2.getFactory().getCodec());
177     }
178 
testTypeFactory()179     public void testTypeFactory() throws Exception
180     {
181         TypeFactory orig = TypeFactory.defaultInstance();
182         JavaType t = orig.constructType(JavaType.class);
183         assertNotNull(t);
184 
185         byte[] bytes = jdkSerialize(orig);
186         TypeFactory result = jdkDeserialize(bytes);
187         assertNotNull(result);
188         t = orig.constructType(JavaType.class);
189         assertEquals(JavaType.class, t.getRawClass());
190     }
191 
testLRUMap()192     public void testLRUMap() throws Exception
193     {
194         LRUMap<String,Integer> map = new LRUMap<String,Integer>(32, 32);
195         map.put("a", 1);
196 
197         byte[] bytes = jdkSerialize(map);
198         LRUMap<String,Integer> result = jdkDeserialize(bytes);
199         // transient implementation, will be read as empty
200         assertEquals(0, result.size());
201 
202         // but should be possible to re-populate
203         result.put("a", 2);
204         assertEquals(1, result.size());
205     }
206 
207     /*
208     /**********************************************************
209     /* Helper methods
210     /**********************************************************
211      */
212 
jdkSerialize(Object o)213     protected byte[] jdkSerialize(Object o) throws IOException
214     {
215         ByteArrayOutputStream bytes = new ByteArrayOutputStream(2000);
216         ObjectOutputStream obOut = new ObjectOutputStream(bytes);
217         obOut.writeObject(o);
218         obOut.close();
219         return bytes.toByteArray();
220     }
221 
222     @SuppressWarnings("unchecked")
jdkDeserialize(byte[] raw)223     protected <T> T jdkDeserialize(byte[] raw) throws IOException
224     {
225         ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(raw));
226         try {
227             return (T) objIn.readObject();
228         } catch (ClassNotFoundException e) {
229             fail("Missing class: "+e.getMessage());
230             return null;
231         } finally {
232             objIn.close();
233         }
234     }
235 }
236