1 package com.fasterxml.jackson.databind.introspect;
2 
3 import java.util.*;
4 
5 import com.fasterxml.jackson.annotation.*;
6 
7 import com.fasterxml.jackson.databind.BaseMapTest;
8 import com.fasterxml.jackson.databind.ObjectMapper;
9 import com.fasterxml.jackson.databind.PropertyNamingStrategy;
10 import com.fasterxml.jackson.databind.annotation.*;
11 import com.fasterxml.jackson.databind.cfg.MapperConfig;
12 import com.fasterxml.jackson.databind.introspect.AnnotatedField;
13 import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
14 
15 /**
16  * Unit tests to verify functioning of {@link PropertyNamingStrategy}.
17  */
18 @SuppressWarnings("serial")
19 public class TestNamingStrategyCustom extends BaseMapTest
20 {
21     /*
22     /**********************************************************************
23     /* Helper classes
24     /**********************************************************************
25      */
26 
27 	static class PrefixStrategy extends PropertyNamingStrategy
28     {
29         @Override
nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName)30         public String nameForField(MapperConfig<?> config,
31                 AnnotatedField field, String defaultName)
32         {
33             return "Field-"+defaultName;
34         }
35 
36         @Override
nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)37         public String nameForGetterMethod(MapperConfig<?> config,
38                 AnnotatedMethod method, String defaultName)
39         {
40             return "Get-"+defaultName;
41         }
42 
43         @Override
nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)44         public String nameForSetterMethod(MapperConfig<?> config,
45                 AnnotatedMethod method, String defaultName)
46         {
47             return "Set-"+defaultName;
48         }
49     }
50 
51     static class CStyleStrategy extends PropertyNamingStrategy
52     {
53         @Override
nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName)54         public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName)
55         {
56             return convert(defaultName);
57         }
58 
59         @Override
nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)60         public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
61         {
62             return convert(defaultName);
63         }
64 
65         @Override
nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)66         public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
67         {
68             return convert(defaultName);
69         }
70 
convert(String input)71         private String convert(String input)
72         {
73             // easy: replace capital letters with underscore, lower-cases equivalent
74             StringBuilder result = new StringBuilder();
75             for (int i = 0, len = input.length(); i < len; ++i) {
76                 char c = input.charAt(i);
77                 if (Character.isUpperCase(c)) {
78                     result.append('_');
79                     c = Character.toLowerCase(c);
80                 }
81                 result.append(c);
82             }
83             return result.toString();
84         }
85     }
86 
87     static class GetterBean {
getKey()88         public int getKey() { return 123; }
89     }
90 
91     static class SetterBean {
92         protected int value;
93 
setKey(int v)94         public void setKey(int v) {
95             value = v;
96         }
97     }
98 
99     static class FieldBean {
100         public int key;
101 
FieldBean()102         public FieldBean() { this(0); }
FieldBean(int v)103         public FieldBean(int v) { key = v; }
104     }
105 
106     @JsonPropertyOrder({"first_name", "last_name"})
107     static class PersonBean {
108         public String firstName;
109         public String lastName;
110         public int age;
111 
PersonBean()112         public PersonBean() { this(null, null, 0); }
PersonBean(String f, String l, int a)113         public PersonBean(String f, String l, int a)
114         {
115             firstName = f;
116             lastName = l;
117             age = a;
118         }
119     }
120 
121     static class Value {
122         public int intValue;
123 
Value()124         public Value() { this(0); }
Value(int v)125         public Value(int v) { intValue = v; }
126     }
127 
128     static class SetterlessWithValue
129     {
130         protected ArrayList<Value> values = new ArrayList<Value>();
131 
getValueList()132         public List<Value> getValueList() { return values; }
133 
add(int v)134         public SetterlessWithValue add(int v) {
135             values.add(new Value(v));
136             return this;
137         }
138     }
139 
140     static class LcStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase
141     {
142         @Override
translate(String propertyName)143         public String translate(String propertyName) {
144             return propertyName.toLowerCase();
145         }
146     }
147 
148     static class RenamedCollectionBean
149     {
150 //        @JsonDeserialize
151         @JsonProperty
152         private List<String> theValues = Collections.emptyList();
153 
154         // intentionally odd name, to be renamed by naming strategy
getTheValues()155         public List<String> getTheValues() { return theValues; }
156     }
157 
158     // [Issue#45]: Support @JsonNaming
159     @JsonNaming(PrefixStrategy.class)
160     static class BeanWithPrefixNames
161     {
162         protected int a = 3;
163 
getA()164         public int getA() { return a; }
setA(int value)165         public void setA(int value) { a = value; }
166     }
167 
168     /*
169     /**********************************************************************
170     /* Test methods
171     /**********************************************************************
172      */
173 
testSimpleGetters()174     public void testSimpleGetters() throws Exception
175     {
176         ObjectMapper mapper = new ObjectMapper();
177         mapper.setPropertyNamingStrategy(new PrefixStrategy());
178         assertEquals("{\"Get-key\":123}", mapper.writeValueAsString(new GetterBean()));
179     }
180 
testSimpleSetters()181     public void testSimpleSetters() throws Exception
182     {
183         ObjectMapper mapper = new ObjectMapper();
184         mapper.setPropertyNamingStrategy(new PrefixStrategy());
185         SetterBean bean = mapper.readValue("{\"Set-key\":13}", SetterBean.class);
186         assertEquals(13, bean.value);
187     }
188 
testSimpleFields()189     public void testSimpleFields() throws Exception
190     {
191         // First serialize
192         ObjectMapper mapper = new ObjectMapper();
193         mapper.setPropertyNamingStrategy(new PrefixStrategy());
194         String json = mapper.writeValueAsString(new FieldBean(999));
195         assertEquals("{\"Field-key\":999}", json);
196 
197         // then deserialize
198         FieldBean result = mapper.readValue(json, FieldBean.class);
199         assertEquals(999, result.key);
200     }
201 
testCStyleNaming()202     public void testCStyleNaming() throws Exception
203     {
204         // First serialize
205         ObjectMapper mapper = new ObjectMapper();
206         mapper.setPropertyNamingStrategy(new CStyleStrategy());
207         String json = mapper.writeValueAsString(new PersonBean("Joe", "Sixpack", 42));
208         assertEquals("{\"first_name\":\"Joe\",\"last_name\":\"Sixpack\",\"age\":42}", json);
209 
210         // then deserialize
211         PersonBean result = mapper.readValue(json, PersonBean.class);
212         assertEquals("Joe", result.firstName);
213         assertEquals("Sixpack", result.lastName);
214         assertEquals(42, result.age);
215     }
216 
testWithGetterAsSetter()217     public void testWithGetterAsSetter() throws Exception
218     {
219         ObjectMapper mapper = new ObjectMapper();
220         mapper.setPropertyNamingStrategy(new CStyleStrategy());
221         SetterlessWithValue input = new SetterlessWithValue().add(3);
222         String json = mapper.writeValueAsString(input);
223         assertEquals("{\"value_list\":[{\"int_value\":3}]}", json);
224 
225         SetterlessWithValue result = mapper.readValue(json, SetterlessWithValue.class);
226         assertNotNull(result.values);
227         assertEquals(1, result.values.size());
228         assertEquals(3, result.values.get(0).intValue);
229     }
230 
testLowerCase()231     public void testLowerCase() throws Exception
232     {
233         ObjectMapper mapper = new ObjectMapper();
234         mapper.setPropertyNamingStrategy(new LcStrategy());
235 //        mapper.disable(DeserializationConfig.DeserializationFeature.USE_GETTERS_AS_SETTERS);
236         RenamedCollectionBean result = mapper.readValue("{\"thevalues\":[\"a\"]}",
237                 RenamedCollectionBean.class);
238         assertNotNull(result.getTheValues());
239         assertEquals(1, result.getTheValues().size());
240         assertEquals("a", result.getTheValues().get(0));
241     }
242 
243     // @JsonNaming / [databind#45]
testPerClassAnnotation()244     public void testPerClassAnnotation() throws Exception
245     {
246         final ObjectMapper mapper = new ObjectMapper();
247         mapper.setPropertyNamingStrategy(new LcStrategy());
248         BeanWithPrefixNames input = new BeanWithPrefixNames();
249         String json = mapper.writeValueAsString(input);
250         assertEquals("{\"Get-a\":3}", json);
251 
252         BeanWithPrefixNames output = mapper.readValue("{\"Set-a\":7}",
253                 BeanWithPrefixNames.class);
254         assertEquals(7, output.a);
255     }
256 }
257