package com.fasterxml.jackson.databind.deser; import java.io.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; /** * This unit test suite tests use of basic Annotations for * bean deserialization; ones that indicate (non-constructor) * method types, explicit deserializer annotations. */ @SuppressWarnings("serial") public class TestBasicAnnotations extends BaseMapTest { /// Class for testing {@link JsonProperty} annotations final static class SizeClassSetter { int _size; int _length; int _other; @JsonProperty public void size(int value) { _size = value; } @JsonProperty("length") public void foobar(int value) { _length = value; } // note: need not be public if annotated @JsonProperty protected void other(int value) { _other = value; } // finally: let's add a red herring that should be avoided... public void errorOut(int value) { throw new Error(); } } static class Issue442Bean { @JsonUnwrapped protected IntWrapper w = new IntWrapper(13); } final static class SizeClassSetter2 { int _x; @JsonProperty public void setX(int value) { _x = value; } // another red herring, which shouldn't be included public void setXandY(int x, int y) { throw new Error(); } } /** * One more, but this time checking for implied setter * using @JsonDeserialize */ final static class SizeClassSetter3 { int _x; @JsonDeserialize public void x(int value) { _x = value; } } /// Classes for testing Setter discovery with inheritance static class BaseBean { int _x = 0, _y = 0; public void setX(int value) { _x = value; } @JsonProperty("y") void foobar(int value) { _y = value; } } static class BeanSubClass extends BaseBean { int _z; public void setZ(int value) { _z = value; } } static class BeanWithDeserialize { @JsonDeserialize protected int a; } @JsonAutoDetect(setterVisibility=Visibility.NONE) final static class Dummy { } final static class EmptyDummy { } static class AnnoBean { int value = 3; @JsonProperty("y") public void setX(int v) { value = v; } } enum Alpha { A, B, C; } public static class SimpleBean { public int x, y; } /* /********************************************************** /* Other helper classes /********************************************************** */ final static class IntsDeserializer extends StdDeserializer<int[]> { public IntsDeserializer() { super(int[].class); } @Override public int[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return new int[] { jp.getIntValue() }; } } /* /********************************************************** /* Test methods, basic /********************************************************** */ private final ObjectMapper MAPPER = new ObjectMapper(); public void testSimpleSetter() throws Exception { SizeClassSetter result = MAPPER.readValue ("{ \"other\":3, \"size\" : 2, \"length\" : -999 }", SizeClassSetter.class); assertEquals(3, result._other); assertEquals(2, result._size); assertEquals(-999, result._length); } // Test for checking [JACKSON-64] public void testSimpleSetter2() throws Exception { SizeClassSetter2 result = MAPPER.readValue("{ \"x\": -3 }", SizeClassSetter2.class); assertEquals(-3, result._x); } // Checking parts of [JACKSON-120] public void testSimpleSetter3() throws Exception { SizeClassSetter3 result = MAPPER.readValue ("{ \"x\": 128 }", SizeClassSetter3.class); assertEquals(128, result._x); } /** * Test for verifying that super-class setters are used as * expected. */ public void testSetterInheritance() throws Exception { BeanSubClass result = MAPPER.readValue ("{ \"x\":1, \"z\" : 3, \"y\" : 2 }", BeanSubClass.class); assertEquals(1, result._x); assertEquals(2, result._y); assertEquals(3, result._z); } public void testImpliedProperty() throws Exception { BeanWithDeserialize bean = MAPPER.readValue("{\"a\":3}", BeanWithDeserialize.class); assertNotNull(bean); assertEquals(3, bean.a); } // [databind#442] public void testIssue442PrivateUnwrapped() throws Exception { Issue442Bean bean = MAPPER.readValue("{\"i\":5}", Issue442Bean.class); assertEquals(5, bean.w.i); } /* /********************************************************** /* Test methods, annotations disabled /********************************************************** */ public void testAnnotationsDisabled() throws Exception { // first: verify that annotation introspection is enabled by default assertTrue(MAPPER.getDeserializationConfig().isEnabled(MapperFeature.USE_ANNOTATIONS)); // with annotations, property is renamed AnnoBean bean = MAPPER.readValue("{ \"y\" : 0 }", AnnoBean.class); assertEquals(0, bean.value); ObjectMapper m = new ObjectMapper(); m.configure(MapperFeature.USE_ANNOTATIONS, false); // without annotations, should default to default bean-based name... bean = m.readValue("{ \"x\" : 0 }", AnnoBean.class); assertEquals(0, bean.value); } public void testEnumsWhenDisabled() throws Exception { ObjectMapper m = new ObjectMapper(); assertEquals(Alpha.B, m.readValue(quote("B"), Alpha.class)); m = new ObjectMapper(); m.configure(MapperFeature.USE_ANNOTATIONS, false); // should still use the basic name handling here assertEquals(Alpha.B, m.readValue(quote("B"), Alpha.class)); } public void testNoAccessOverrides() throws Exception { ObjectMapper m = new ObjectMapper(); m.disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS); SimpleBean bean = m.readValue("{\"x\":1,\"y\":2}", SimpleBean.class); assertEquals(1, bean.x); assertEquals(2, bean.y); } }