package com.fasterxml.jackson.databind.ser; import java.io.StringWriter; import java.text.SimpleDateFormat; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.introspect.ClassIntrospector; /** * Unit tests for checking handling of SerializationConfig. */ public class TestConfig extends BaseMapTest { /* /********************************************************** /* Helper beans /********************************************************** */ @JsonInclude(JsonInclude.Include.NON_DEFAULT) @JsonSerialize(typing=JsonSerialize.Typing.STATIC) final static class Config { } final static class ConfigNone { } static class AnnoBean { public int getX() { return 1; } @JsonProperty("y") private int getY() { return 2; } } static class Indentable { public int a = 3; } public static class SimpleBean { public int x = 1; } /* /********************************************************** /* Main tests /********************************************************** */ final static ObjectMapper MAPPER = new ObjectMapper(); /* Test to verify that we don't overflow number of features; if we * hit the limit, need to change implementation -- this test just * gives low-water mark */ public void testEnumIndexes() { int max = 0; for (SerializationFeature f : SerializationFeature.values()) { max = Math.max(max, f.ordinal()); } if (max >= 31) { // 31 is actually ok; 32 not fail("Max number of SerializationFeature enums reached: "+max); } } public void testDefaults() { SerializationConfig cfg = MAPPER.getSerializationConfig(); // First, defaults: assertTrue(cfg.isEnabled(MapperFeature.USE_ANNOTATIONS)); assertTrue(cfg.isEnabled(MapperFeature.AUTO_DETECT_GETTERS)); assertTrue(cfg.isEnabled(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)); assertTrue(cfg.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)); assertFalse(cfg.isEnabled(SerializationFeature.INDENT_OUTPUT)); assertFalse(cfg.isEnabled(MapperFeature.USE_STATIC_TYPING)); // since 1.3: assertTrue(cfg.isEnabled(MapperFeature.AUTO_DETECT_IS_GETTERS)); // since 1.4 assertTrue(cfg.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)); // since 1.5 assertTrue(cfg.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION)); } public void testOverrideIntrospectors() { SerializationConfig cfg = MAPPER.getSerializationConfig(); // and finally, ensure we could override introspectors cfg = cfg.with((ClassIntrospector) null); // no way to verify tho cfg = cfg.with((AnnotationIntrospector) null); assertNull(cfg.getAnnotationIntrospector()); } public void testMisc() { ObjectMapper m = new ObjectMapper(); m.setDateFormat(null); // just to execute the code path assertNotNull(m.getSerializationConfig().toString()); // ditto } public void testIndentation() throws Exception { Map<String,Integer> map = new HashMap<String,Integer>(); map.put("a", Integer.valueOf(2)); String result = MAPPER.writer().with(SerializationFeature.INDENT_OUTPUT) .writeValueAsString(map); // 02-Jun-2009, tatu: not really a clean way but... String lf = getLF(); assertEquals("{"+lf+" \"a\" : 2"+lf+"}", result); } public void testAnnotationsDisabled() throws Exception { // first: verify that annotation introspection is enabled by default assertTrue(MAPPER.isEnabled(MapperFeature.USE_ANNOTATIONS)); Map<String,Object> result = writeAndMap(MAPPER, new AnnoBean()); assertEquals(2, result.size()); ObjectMapper m2 = new ObjectMapper(); m2.configure(MapperFeature.USE_ANNOTATIONS, false); result = writeAndMap(m2, new AnnoBean()); assertEquals(1, result.size()); } /** * Test for verifying working of [JACKSON-191] */ public void testProviderConfig() throws Exception { ObjectMapper mapper = new ObjectMapper(); DefaultSerializerProvider prov = (DefaultSerializerProvider) mapper.getSerializerProvider(); assertEquals(0, prov.cachedSerializersCount()); // and then should get one constructed for: Map<String,Object> result = this.writeAndMap(mapper, new AnnoBean()); assertEquals(2, result.size()); assertEquals(Integer.valueOf(1), result.get("x")); assertEquals(Integer.valueOf(2), result.get("y")); /* Note: it is 2 because we'll also get serializer for basic 'int', not * just AnnoBean */ /* 12-Jan-2010, tatus: Actually, probably more, if and when we typing * aspects are considered (depending on what is cached) */ int count = prov.cachedSerializersCount(); if (count < 2) { fail("Should have at least 2 cached serializers, got "+count); } prov.flushCachedSerializers(); assertEquals(0, prov.cachedSerializersCount()); } // Test for [Issue#12] public void testIndentWithPassedGenerator() throws Exception { Indentable input = new Indentable(); assertEquals("{\"a\":3}", MAPPER.writeValueAsString(input)); String LF = getLF(); String INDENTED = "{"+LF+" \"a\" : 3"+LF+"}"; final ObjectWriter indentWriter = MAPPER.writer().with(SerializationFeature.INDENT_OUTPUT); assertEquals(INDENTED, indentWriter.writeValueAsString(input)); // [Issue#12] StringWriter sw = new StringWriter(); JsonGenerator jgen = MAPPER.getFactory().createGenerator(sw); indentWriter.writeValue(jgen, input); jgen.close(); assertEquals(INDENTED, sw.toString()); // and also with ObjectMapper itself sw = new StringWriter(); ObjectMapper m2 = new ObjectMapper(); m2.enable(SerializationFeature.INDENT_OUTPUT); jgen = m2.getFactory().createGenerator(sw); m2.writeValue(jgen, input); jgen.close(); assertEquals(INDENTED, sw.toString()); } public void testNoAccessOverrides() throws Exception { ObjectMapper m = new ObjectMapper(); m.disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS); assertEquals("{\"x\":1}", m.writeValueAsString(new SimpleBean())); } public void testDateFormatConfig() throws Exception { ObjectMapper mapper = new ObjectMapper(); TimeZone tz1 = TimeZone.getTimeZone("America/Los_Angeles"); TimeZone tz2 = TimeZone.getTimeZone("Central Standard Time"); // sanity checks assertEquals(tz1, tz1); assertEquals(tz2, tz2); if (tz1.equals(tz2)) { fail(); } mapper.setTimeZone(tz1); assertEquals(tz1, mapper.getSerializationConfig().getTimeZone()); assertEquals(tz1, mapper.getDeserializationConfig().getTimeZone()); // also better stick via reader/writer as well assertEquals(tz1, mapper.writer().getConfig().getTimeZone()); assertEquals(tz1, mapper.reader().getConfig().getTimeZone()); SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); f.setTimeZone(tz2); mapper.setDateFormat(f); // should not change the timezone tho assertEquals(tz1, mapper.getSerializationConfig().getTimeZone()); assertEquals(tz1, mapper.getDeserializationConfig().getTimeZone()); assertEquals(tz1, mapper.writer().getConfig().getTimeZone()); assertEquals(tz1, mapper.reader().getConfig().getTimeZone()); } private final static String getLF() { return System.getProperty("line.separator"); } }