1 package com.fasterxml.jackson.databind; 2 3 import java.io.*; 4 import java.math.BigDecimal; 5 import java.math.BigInteger; 6 import java.util.*; 7 8 import static org.junit.Assert.*; 9 10 import com.fasterxml.jackson.annotation.JsonCreator; 11 12 import com.fasterxml.jackson.core.*; 13 14 import com.fasterxml.jackson.databind.ObjectMapper; 15 import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; 16 import com.fasterxml.jackson.databind.json.JsonMapper; 17 import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; 18 import com.fasterxml.jackson.databind.type.TypeFactory; 19 20 public abstract class BaseMapTest 21 extends BaseTest 22 { 23 private final static Object SINGLETON_OBJECT = new Object(); 24 25 /* 26 /********************************************************** 27 /* Shared helper classes 28 /********************************************************** 29 */ 30 31 public static class BogusSchema implements FormatSchema { 32 @Override getSchemaType()33 public String getSchemaType() { 34 return "TestFormat"; 35 } 36 } 37 38 /** 39 * Simple wrapper around boolean types, usually to test value 40 * conversions or wrapping 41 */ 42 protected static class BooleanWrapper { 43 public Boolean b; 44 BooleanWrapper()45 public BooleanWrapper() { } BooleanWrapper(Boolean value)46 public BooleanWrapper(Boolean value) { b = value; } 47 } 48 49 protected static class IntWrapper { 50 public int i; 51 IntWrapper()52 public IntWrapper() { } IntWrapper(int value)53 public IntWrapper(int value) { i = value; } 54 } 55 56 protected static class LongWrapper { 57 public long l; 58 LongWrapper()59 public LongWrapper() { } LongWrapper(long value)60 public LongWrapper(long value) { l = value; } 61 } 62 63 protected static class BigIntegerWrapper { 64 public BigInteger i; 65 BigIntegerWrapper()66 public BigIntegerWrapper() { } 67 BigIntegerWrapper(final BigInteger value)68 public BigIntegerWrapper(final BigInteger value) { i = value; } 69 } 70 71 protected static class DoubleWrapper { 72 public double d; 73 DoubleWrapper()74 public DoubleWrapper() { } DoubleWrapper(double value)75 public DoubleWrapper(double value) { d = value; } 76 } 77 78 protected static class BigDecimalWrapper { 79 public BigDecimal d; 80 BigDecimalWrapper()81 public BigDecimalWrapper() { } 82 BigDecimalWrapper(final BigDecimal value)83 public BigDecimalWrapper(final BigDecimal value) { d = value; } 84 } 85 86 /** 87 * Simple wrapper around String type, usually to test value 88 * conversions or wrapping 89 */ 90 protected static class StringWrapper { 91 public String str; 92 StringWrapper()93 public StringWrapper() { } StringWrapper(String value)94 public StringWrapper(String value) { 95 str = value; 96 } 97 } 98 99 protected static class ObjectWrapper { 100 final Object object; ObjectWrapper(final Object object)101 protected ObjectWrapper(final Object object) { 102 this.object = object; 103 } getObject()104 public Object getObject() { return object; } 105 @JsonCreator jsonValue(final Object object)106 static ObjectWrapper jsonValue(final Object object) { 107 return new ObjectWrapper(object); 108 } 109 } 110 111 protected static class ListWrapper<T> 112 { 113 public List<T> list; 114 ListWrapper(@uppressWarnings"unchecked") T... values)115 public ListWrapper(@SuppressWarnings("unchecked") T... values) { 116 list = new ArrayList<T>(); 117 for (T value : values) { 118 list.add(value); 119 } 120 } 121 } 122 123 protected static class MapWrapper<K,V> 124 { 125 public Map<K,V> map; 126 MapWrapper()127 public MapWrapper() { } MapWrapper(Map<K,V> m)128 public MapWrapper(Map<K,V> m) { 129 map = m; 130 } MapWrapper(K key, V value)131 public MapWrapper(K key, V value) { 132 map = new LinkedHashMap<>(); 133 map.put(key, value); 134 } 135 } 136 137 protected static class ArrayWrapper<T> 138 { 139 public T[] array; 140 ArrayWrapper(T[] v)141 public ArrayWrapper(T[] v) { 142 array = v; 143 } 144 } 145 146 /** 147 * Enumeration type with sub-classes per value. 148 */ 149 protected enum EnumWithSubClass { foobar()150 A { @Override public void foobar() { } } foobar()151 ,B { @Override public void foobar() { } } 152 ; 153 foobar()154 public abstract void foobar(); 155 } 156 157 public enum ABC { A, B, C; } 158 159 // since 2.8 160 public static class Point { 161 public int x, y; 162 Point()163 protected Point() { } // for deser Point(int x0, int y0)164 public Point(int x0, int y0) { 165 x = x0; 166 y = y0; 167 } 168 169 @Override equals(Object o)170 public boolean equals(Object o) { 171 if (!(o instanceof Point)) { 172 return false; 173 } 174 Point other = (Point) o; 175 return (other.x == x) && (other.y == y); 176 } 177 178 @Override toString()179 public String toString() { 180 return String.format("[x=%d, y=%d]", x, y); 181 } 182 } 183 184 /* 185 /********************************************************** 186 /* Shared serializers 187 /********************************************************** 188 */ 189 190 @SuppressWarnings("serial") 191 public static class UpperCasingSerializer extends StdScalarSerializer<String> 192 { UpperCasingSerializer()193 public UpperCasingSerializer() { super(String.class); } 194 195 @Override serialize(String value, JsonGenerator gen, SerializerProvider provider)196 public void serialize(String value, JsonGenerator gen, 197 SerializerProvider provider) throws IOException { 198 gen.writeString(value.toUpperCase()); 199 } 200 } 201 202 @SuppressWarnings("serial") 203 public static class LowerCasingDeserializer extends StdScalarDeserializer<String> 204 { LowerCasingDeserializer()205 public LowerCasingDeserializer() { super(String.class); } 206 207 @Override deserialize(JsonParser p, DeserializationContext ctxt)208 public String deserialize(JsonParser p, DeserializationContext ctxt) 209 throws IOException, JsonProcessingException { 210 return p.getText().toLowerCase(); 211 } 212 } 213 214 /* 215 /********************************************************** 216 /* Construction 217 /********************************************************** 218 */ 219 BaseMapTest()220 protected BaseMapTest() { super(); } 221 222 /* 223 /********************************************************** 224 /* Factory methods 225 /********************************************************** 226 */ 227 228 private static ObjectMapper SHARED_MAPPER; 229 sharedMapper()230 protected ObjectMapper sharedMapper() { 231 if (SHARED_MAPPER == null) { 232 SHARED_MAPPER = newJsonMapper(); 233 } 234 return SHARED_MAPPER; 235 } 236 objectMapper()237 protected ObjectMapper objectMapper() { 238 return sharedMapper(); 239 } 240 objectWriter()241 protected ObjectWriter objectWriter() { 242 return sharedMapper().writer(); 243 } 244 objectReader()245 protected ObjectReader objectReader() { 246 return sharedMapper().reader(); 247 } 248 objectReader(Class<?> cls)249 protected ObjectReader objectReader(Class<?> cls) { 250 return sharedMapper().readerFor(cls); 251 } 252 253 // @since 2.10 newJsonMapper()254 protected static ObjectMapper newJsonMapper() { 255 return new JsonMapper(); 256 } 257 258 // @since 2.10 jsonMapperBuilder()259 protected static JsonMapper.Builder jsonMapperBuilder() { 260 return JsonMapper.builder(); 261 } 262 263 // @since 2.7 newTypeFactory()264 protected TypeFactory newTypeFactory() { 265 // this is a work-around; no null modifier added 266 return TypeFactory.defaultInstance().withModifier(null); 267 } 268 269 /* 270 /********************************************************** 271 /* Additional assert methods 272 /********************************************************** 273 */ 274 assertEquals(int[] exp, int[] act)275 protected void assertEquals(int[] exp, int[] act) 276 { 277 assertArrayEquals(exp, act); 278 } 279 assertEquals(byte[] exp, byte[] act)280 protected void assertEquals(byte[] exp, byte[] act) 281 { 282 assertArrayEquals(exp, act); 283 } 284 285 /** 286 * Helper method for verifying 3 basic cookie cutter cases; 287 * identity comparison (true), and against null (false), 288 * or object of different type (false) 289 */ assertStandardEquals(Object o)290 protected void assertStandardEquals(Object o) 291 { 292 assertTrue(o.equals(o)); 293 assertFalse(o.equals(null)); 294 assertFalse(o.equals(SINGLETON_OBJECT)); 295 // just for fun, let's also call hash code... 296 o.hashCode(); 297 } 298 299 /* 300 /********************************************************** 301 /* Helper methods, serialization 302 /********************************************************** 303 */ 304 305 @SuppressWarnings("unchecked") writeAndMap(ObjectMapper m, Object value)306 protected Map<String,Object> writeAndMap(ObjectMapper m, Object value) 307 throws IOException 308 { 309 String str = m.writeValueAsString(value); 310 return (Map<String,Object>) m.readValue(str, Map.class); 311 } 312 serializeAsString(ObjectMapper m, Object value)313 protected String serializeAsString(ObjectMapper m, Object value) 314 throws IOException 315 { 316 return m.writeValueAsString(value); 317 } 318 serializeAsString(Object value)319 protected String serializeAsString(Object value) 320 throws IOException 321 { 322 return serializeAsString(sharedMapper(), value); 323 } 324 asJSONObjectValueString(Object... args)325 protected String asJSONObjectValueString(Object... args) 326 throws IOException 327 { 328 return asJSONObjectValueString(sharedMapper(), args); 329 } 330 asJSONObjectValueString(ObjectMapper m, Object... args)331 protected String asJSONObjectValueString(ObjectMapper m, Object... args) 332 throws IOException 333 { 334 LinkedHashMap<Object,Object> map = new LinkedHashMap<Object,Object>(); 335 for (int i = 0, len = args.length; i < len; i += 2) { 336 map.put(args[i], args[i+1]); 337 } 338 return m.writeValueAsString(map); 339 } 340 341 /* 342 /********************************************************** 343 /* Helper methods, deserialization 344 /********************************************************** 345 */ 346 readAndMapFromString(String input, Class<T> cls)347 protected <T> T readAndMapFromString(String input, Class<T> cls) 348 throws IOException 349 { 350 return readAndMapFromString(sharedMapper(), input, cls); 351 } 352 readAndMapFromString(ObjectMapper m, String input, Class<T> cls)353 protected <T> T readAndMapFromString(ObjectMapper m, String input, Class<T> cls) throws IOException 354 { 355 return (T) m.readValue("\""+input+"\"", cls); 356 } 357 358 /* 359 /********************************************************** 360 /* Helper methods, other 361 /********************************************************** 362 */ 363 getUTCTimeZone()364 protected TimeZone getUTCTimeZone() { 365 return TimeZone.getTimeZone("GMT"); 366 } 367 utf8Bytes(String str)368 protected byte[] utf8Bytes(String str) { 369 try { 370 return str.getBytes("UTF-8"); 371 } catch (IOException e) { 372 throw new IllegalArgumentException(e); 373 } 374 } 375 aposToQuotes(String json)376 protected static String aposToQuotes(String json) { 377 return json.replace("'", "\""); 378 } 379 a2q(String json)380 protected static String a2q(String json) { 381 return json.replace("'", "\""); 382 } 383 quotesToApos(String json)384 protected static String quotesToApos(String json) { 385 return json.replace("\"", "'"); 386 } 387 } 388