• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.ser;
2 
3 import java.util.*;
4 
5 import com.fasterxml.jackson.annotation.*;
6 import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
7 import com.fasterxml.jackson.databind.*;
8 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
9 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
10 
11 /**
12  * Unit tests for verifying that field-backed properties can also be serialized
13  * (since version 1.1) as well as getter-accessible properties.
14  */
15 public class FieldSerializationTest
16     extends BaseMapTest
17 {
18     /*
19     /**********************************************************
20     /* Annotated helper classes
21     /**********************************************************
22      */
23 
24     static class SimpleFieldBean
25     {
26         public int x, y;
27 
28         // not auto-detectable, not public
29         int z;
30 
31         // ignored, not detectable either
32         @JsonIgnore public int a;
33     }
34 
35     static class SimpleFieldBean2
36     {
37         @JsonSerialize String[] values;
38 
39         // note: this annotation should not matter for serialization:
40         @JsonDeserialize int dummy;
41     }
42 
43     static class TransientBean
44     {
45         public int a;
46         // transients should not be included
47         public transient int b;
48         // or statics
49         public static int c;
50     }
51 
52     @JsonAutoDetect(setterVisibility=Visibility.PUBLIC_ONLY, fieldVisibility=Visibility.NONE)
53     public class NoAutoDetectBean
54     {
55         // not auto-detectable any more
56         public int x;
57 
58         @JsonProperty("z")
59         public int _z;
60     }
61 
62     /**
63      * Let's test invalid bean too: can't have 2 logical properties
64      * with same name.
65      *<p>
66      * 21-Feb-2010, tatus: That is, not within same class.
67      *    As per [JACKSON-226] it is acceptable to "override"
68      *    field definitions in sub-classes.
69      */
70     public static class DupFieldBean
71     {
72         @JsonProperty("foo")
73         public int _z;
74 
75         @JsonSerialize
76         private int foo;
77     }
78 
79     public static class DupFieldBean2
80     {
81         public int z;
82 
83         @JsonProperty("z")
84         public int _z;
85     }
86 
87     @SuppressWarnings("hiding")
88     public static class OkDupFieldBean
89         extends SimpleFieldBean
90     {
91         @JsonProperty("x")
92         protected int myX;
93 
94         public int y;
95 
OkDupFieldBean(int x, int y)96         public OkDupFieldBean(int x, int y) {
97             this.myX = x;
98             this.y = y;
99         }
100     }
101 
102     /**
103      * It is ok to have a method-based and field-based property
104      * introspectable: only one should be serialized, and since
105      * methods have precedence, it should be the method one.
106      */
107     public static class FieldAndMethodBean
108     {
109         @JsonProperty public int z;
110 
getZ()111         @JsonProperty("z") public int getZ() { return z+1; }
112     }
113 
114     @JsonInclude(JsonInclude.Include.NON_EMPTY)
115     public class Item240 {
116         @JsonProperty
117         private String id;
118         // only include annotation to ensure it won't override settings
119         @JsonSerialize(typing=JsonSerialize.Typing.STATIC)
120         private String state;
121 
Item240(String id, String state)122         public Item240(String id, String state) {
123             this.id = id;
124             this.state = state;
125         }
126     }
127 
128     /*
129     /**********************************************************
130     /* Main tests, success
131     /**********************************************************
132      */
133 
134     private final ObjectMapper MAPPER = newJsonMapper();
135 
testSimpleAutoDetect()136     public void testSimpleAutoDetect() throws Exception
137     {
138         SimpleFieldBean bean = new SimpleFieldBean();
139         // let's set x, leave y as is
140         bean.x = 13;
141         Map<String,Object> result = writeAndMap(MAPPER, bean);
142         assertEquals(2, result.size());
143         assertEquals(Integer.valueOf(13), result.get("x"));
144         assertEquals(Integer.valueOf(0), result.get("y"));
145     }
146 
147     @SuppressWarnings("unchecked")
testSimpleAnnotation()148 	public void testSimpleAnnotation() throws Exception
149     {
150         SimpleFieldBean2 bean = new SimpleFieldBean2();
151         bean.values = new String[] { "a", "b" };
152         Map<String,Object> result = writeAndMap(MAPPER, bean);
153         assertEquals(1, result.size());
154         List<String> values = (List<String>) result.get("values");
155         assertEquals(2, values.size());
156         assertEquals("a", values.get(0));
157         assertEquals("b", values.get(1));
158     }
159 
testTransientAndStatic()160     public void testTransientAndStatic() throws Exception
161     {
162         TransientBean bean = new TransientBean();
163         Map<String,Object> result = writeAndMap(MAPPER, bean);
164         assertEquals(1, result.size());
165         assertEquals(Integer.valueOf(0), result.get("a"));
166     }
167 
testNoAutoDetect()168     public void testNoAutoDetect() throws Exception
169     {
170         NoAutoDetectBean bean = new NoAutoDetectBean();
171         bean._z = -4;
172         Map<String,Object> result = writeAndMap(MAPPER, bean);
173         assertEquals(1, result.size());
174         assertEquals(Integer.valueOf(-4), result.get("z"));
175     }
176 
177     /**
178      * Unit test that verifies that if both a field and a getter
179      * method exist for a logical property (which is allowed),
180      * getter has precendence over field.
181      */
testMethodPrecedence()182     public void testMethodPrecedence() throws Exception
183     {
184         FieldAndMethodBean bean = new FieldAndMethodBean();
185         bean.z = 9;
186         assertEquals(10, bean.getZ());
187         assertEquals("{\"z\":10}", MAPPER.writeValueAsString(bean));
188     }
189 
190     /**
191      * Testing [JACKSON-226]: it is ok to have "field override",
192      * as long as there are no intra-class conflicts.
193      */
testOkDupFields()194     public void testOkDupFields() throws Exception
195     {
196         OkDupFieldBean bean = new OkDupFieldBean(1, 2);
197         Map<String,Object> json = writeAndMap(MAPPER, bean);
198         assertEquals(2, json.size());
199         assertEquals(Integer.valueOf(1), json.get("x"));
200         assertEquals(Integer.valueOf(2), json.get("y"));
201     }
202 
testIssue240()203     public void testIssue240() throws Exception
204     {
205         Item240 bean = new Item240("a12", null);
206         assertEquals(MAPPER.writeValueAsString(bean), "{\"id\":\"a12\"}");
207     }
208 
209     /*
210     /**********************************************************
211     /* Main tests, failure cases
212     /**********************************************************
213      */
214 
testFailureDueToDups()215     public void testFailureDueToDups() throws Exception
216     {
217         try {
218             writeAndMap(MAPPER, new DupFieldBean());
219         } catch (JsonMappingException e) {
220             verifyException(e, "Multiple fields representing");
221         }
222     }
223 
testFailureDueToDupField()224     public void testFailureDueToDupField() throws Exception
225     {
226         try {
227             writeAndMap(MAPPER, new DupFieldBean2());
228         } catch (JsonMappingException e) {
229             verifyException(e, "Multiple fields representing");
230         }
231     }
232 }
233 
234