• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.convert;
2 
3 import java.io.IOException;
4 import java.util.*;
5 
6 import com.fasterxml.jackson.annotation.*;
7 import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
8 import com.fasterxml.jackson.core.*;
9 import com.fasterxml.jackson.databind.*;
10 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
11 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
12 import com.fasterxml.jackson.databind.module.SimpleModule;
13 
14 import static org.junit.Assert.assertArrayEquals;
15 
16 /**
17  * Unit tests for verifying that "updating reader" works as
18  * expected.
19  */
20 @SuppressWarnings("serial")
21 public class TestUpdateViaObjectReader extends BaseMapTest
22 {
23     static class Bean {
24         public String a = "a";
25         public String b = "b";
26 
27         public int[] c = new int[] { 1, 2, 3 };
28 
29         public Bean child = null;
30     }
31 
32     static class XYBean {
33         public int x, y;
34     }
35 
36     public class TextView {}
37     public class NumView {}
38 
39     public class Updateable {
40         @JsonView(NumView.class)
41         public int num;
42 
43         @JsonView(TextView.class)
44         public String str;
45     }
46 
47     // for [databind#744]
48     static class DataA {
49         public int i = 1;
50         public int j = 2;
51 
52     }
53 
54     static class DataB {
55         public DataA da = new DataA();
56         public int k = 3;
57     }
58 
59     static class DataADeserializer extends StdDeserializer<DataA> {
60         private static final long serialVersionUID = 1L;
61 
DataADeserializer()62         DataADeserializer() {
63             super(DataA.class);
64         }
65 
66         @Override
deserialize(JsonParser p, DeserializationContext ctxt)67         public DataA deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
68             if (p.currentToken() != JsonToken.START_OBJECT) {
69                 ctxt.reportInputMismatch(DataA.class,
70                         "Wrong current token, expected START_OBJECT, got: "
71                         +p.currentToken());
72                 // never gets here
73             }
74             /*JsonNode node =*/ p.readValueAsTree();
75 
76             DataA da = new DataA();
77             da.i = 5;
78             return da;
79         }
80     }
81 
82     // [databind#1831]
83     @JsonTypeInfo(use = Id.NAME)
84     @JsonSubTypes({  @JsonSubTypes.Type(value = Cat.class) })
85     static abstract public class AbstractAnimal { }
86 
87     @JsonDeserialize(using = AnimalWrapperDeserializer.class)
88     static class AnimalWrapper {
89         @JsonUnwrapped
90         protected AbstractAnimal animal;
91 
setAnimal(AbstractAnimal animal)92         public void setAnimal(AbstractAnimal animal) {
93             this.animal = animal;
94         }
95     }
96 
97     static class Cat extends AbstractAnimal { }
98 
99     static class AnimalWrapperDeserializer extends StdDeserializer<AnimalWrapper> {
AnimalWrapperDeserializer()100         public AnimalWrapperDeserializer() {
101             super(AnimalWrapper.class);
102         }
103 
104         @Override
deserialize(JsonParser json, DeserializationContext context)105         public AnimalWrapper deserialize(JsonParser json, DeserializationContext context) throws IOException {
106             AnimalWrapper msg = new AnimalWrapper();
107             msg.setAnimal(json.readValueAs(AbstractAnimal.class));
108             return msg;
109         }
110 
111         @Override
deserialize(JsonParser json, DeserializationContext context, AnimalWrapper intoValue)112         public AnimalWrapper deserialize(JsonParser json, DeserializationContext context, AnimalWrapper intoValue) throws IOException {
113             intoValue.setAnimal(json.readValueAs(AbstractAnimal.class));
114             return intoValue;
115         }
116     }
117 
118     /*
119     /********************************************************
120     /* Test methods
121     /********************************************************
122      */
123 
124     private final ObjectMapper MAPPER = new ObjectMapper();
125 
testBeanUpdate()126     public void testBeanUpdate() throws Exception
127     {
128         Bean bean = new Bean();
129         assertEquals("b", bean.b);
130         assertEquals(3, bean.c.length);
131         assertNull(bean.child);
132 
133         Object ob = MAPPER.readerForUpdating(bean).readValue("{ \"b\":\"x\", \"c\":[4,5], \"child\":{ \"a\":\"y\"} }");
134         assertSame(ob, bean);
135 
136         assertEquals("a", bean.a);
137         assertEquals("x", bean.b);
138         assertArrayEquals(new int[] { 4, 5 }, bean.c);
139 
140         Bean child = bean.child;
141         assertNotNull(child);
142         assertEquals("y", child.a);
143         assertEquals("b", child.b);
144         assertArrayEquals(new int[] { 1, 2, 3 }, child.c);
145         assertNull(child.child);
146     }
147 
testListUpdate()148     public void testListUpdate() throws Exception
149     {
150         List<String> strs = new ArrayList<String>();
151         strs.add("a");
152         // for lists, we will be appending entries
153         Object ob = MAPPER.readerForUpdating(strs).readValue("[ \"b\", \"c\", \"d\" ]");
154         assertSame(strs, ob);
155         assertEquals(4, strs.size());
156         assertEquals("a", strs.get(0));
157         assertEquals("b", strs.get(1));
158         assertEquals("c", strs.get(2));
159         assertEquals("d", strs.get(3));
160     }
161 
testMapUpdate()162     public void testMapUpdate() throws Exception
163     {
164         Map<String,String> strs = new HashMap<String,String>();
165         strs.put("a", "a");
166         strs.put("b", "b");
167         // for maps, we will be adding and/or overwriting entries
168         Object ob = MAPPER.readerForUpdating(strs).readValue("{ \"c\" : \"c\", \"a\" : \"z\" }");
169         assertSame(strs, ob);
170         assertEquals(3, strs.size());
171         assertEquals("z", strs.get("a"));
172         assertEquals("b", strs.get("b"));
173         assertEquals("c", strs.get("c"));
174     }
175 
176     // Test for [JACKSON-717] -- ensure 'readValues' also does update
177     @SuppressWarnings("resource")
testUpdateSequence()178     public void testUpdateSequence() throws Exception
179     {
180         XYBean toUpdate = new XYBean();
181         Iterator<XYBean> it = MAPPER.readerForUpdating(toUpdate).readValues(
182                 "{\"x\":1,\"y\":2}\n{\"x\":16}{\"y\":37}");
183 
184         assertTrue(it.hasNext());
185         XYBean value = it.next();
186         assertSame(toUpdate, value);
187         assertEquals(1, value.x);
188         assertEquals(2, value.y);
189 
190         assertTrue(it.hasNext());
191         value = it.next();
192         assertSame(toUpdate, value);
193         assertEquals(16, value.x);
194         assertEquals(2, value.y); // unchanged
195 
196         assertTrue(it.hasNext());
197         value = it.next();
198         assertSame(toUpdate, value);
199         assertEquals(16, value.x); // unchanged
200         assertEquals(37, value.y);
201 
202         assertFalse(it.hasNext());
203     }
204 
205     // [JACKSON-824]
testUpdatingWithViews()206     public void testUpdatingWithViews() throws Exception
207     {
208         Updateable bean = new Updateable();
209         bean.num = 100;
210         bean.str = "test";
211         Updateable result = MAPPER.readerForUpdating(bean)
212                 .withView(TextView.class)
213                 .readValue("{\"num\": 10, \"str\":\"foobar\"}");
214         assertSame(bean, result);
215 
216         assertEquals(100, bean.num);
217         assertEquals("foobar", bean.str);
218     }
219 
220     // [databind#744]
testIssue744()221     public void testIssue744() throws IOException
222     {
223         ObjectMapper mapper = new ObjectMapper();
224         SimpleModule module = new SimpleModule();
225         module.addDeserializer(DataA.class, new DataADeserializer());
226         mapper.registerModule(module);
227 
228         DataB db = new DataB();
229         db.da.i = 11;
230         db.k = 13;
231         String jsonBString = mapper.writeValueAsString(db);
232         JsonNode jsonBNode = mapper.valueToTree(db);
233 
234         // create parent
235         DataB dbNewViaString = mapper.readValue(jsonBString, DataB.class);
236         assertEquals(5, dbNewViaString.da.i);
237         assertEquals(13, dbNewViaString.k);
238 
239         DataB dbNewViaNode = mapper.treeToValue(jsonBNode, DataB.class);
240         assertEquals(5, dbNewViaNode.da.i);
241         assertEquals(13, dbNewViaNode.k);
242 
243         // update parent
244         DataB dbUpdViaString = new DataB();
245         DataB dbUpdViaNode = new DataB();
246 
247         assertEquals(1, dbUpdViaString.da.i);
248         assertEquals(3, dbUpdViaString.k);
249         mapper.readerForUpdating(dbUpdViaString).readValue(jsonBString);
250         assertEquals(5, dbUpdViaString.da.i);
251         assertEquals(13, dbUpdViaString.k);
252 
253         assertEquals(1, dbUpdViaNode.da.i);
254         assertEquals(3, dbUpdViaNode.k);
255 
256         mapper.readerForUpdating(dbUpdViaNode).readValue(jsonBNode);
257         assertEquals(5, dbUpdViaNode.da.i);
258         assertEquals(13, dbUpdViaNode.k);
259     }
260 
261     // [databind#1831]
test1831UsingNode()262     public void test1831UsingNode() throws IOException {
263         String catJson = MAPPER.writeValueAsString(new Cat());
264         JsonNode jsonNode = MAPPER.readTree(catJson);
265         AnimalWrapper optionalCat = new AnimalWrapper();
266         ObjectReader r = MAPPER.readerForUpdating(optionalCat);
267         AnimalWrapper result = r.readValue(jsonNode);
268         assertSame(optionalCat, result);
269     }
270 
test1831UsingString()271     public void test1831UsingString() throws IOException {
272         String catJson = MAPPER.writeValueAsString(new Cat());
273         AnimalWrapper optionalCat = new AnimalWrapper();
274         AnimalWrapper result = MAPPER.readerForUpdating(optionalCat).readValue(catJson);
275         assertSame(optionalCat, result);
276     }
277 }
278