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