1 package com.fasterxml.jackson.databind.introspect; 2 3 import java.io.IOException; 4 import java.io.StringWriter; 5 import java.util.*; 6 7 import javax.xml.namespace.QName; 8 9 import com.fasterxml.jackson.annotation.*; 10 import com.fasterxml.jackson.core.JsonGenerator; 11 import com.fasterxml.jackson.core.JsonParser; 12 import com.fasterxml.jackson.core.JsonProcessingException; 13 import com.fasterxml.jackson.databind.*; 14 import com.fasterxml.jackson.databind.annotation.*; 15 import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 16 import com.fasterxml.jackson.databind.introspect.AnnotatedClass; 17 import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; 18 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; 19 import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder; 20 import com.fasterxml.jackson.databind.type.TypeFactory; 21 22 @SuppressWarnings("serial") 23 public class TestJacksonAnnotationIntrospector 24 extends BaseMapTest 25 { 26 public static enum EnumExample { 27 VALUE1; 28 } 29 30 public static class JacksonExample 31 { 32 protected String attributeProperty; 33 protected String elementProperty; 34 protected List<String> wrappedElementProperty; 35 protected EnumExample enumProperty; 36 protected QName qname; 37 38 @JsonSerialize(using=QNameSerializer.class) getQname()39 public QName getQname() 40 { 41 return qname; 42 } 43 44 @JsonDeserialize(using=QNameDeserializer.class) setQname(QName qname)45 public void setQname(QName qname) 46 { 47 this.qname = qname; 48 } 49 50 @JsonProperty("myattribute") getAttributeProperty()51 public String getAttributeProperty() 52 { 53 return attributeProperty; 54 } 55 56 @JsonProperty("myattribute") setAttributeProperty(String attributeProperty)57 public void setAttributeProperty(String attributeProperty) 58 { 59 this.attributeProperty = attributeProperty; 60 } 61 62 @JsonProperty("myelement") getElementProperty()63 public String getElementProperty() 64 { 65 return elementProperty; 66 } 67 68 @JsonProperty("myelement") setElementProperty(String elementProperty)69 public void setElementProperty(String elementProperty) 70 { 71 this.elementProperty = elementProperty; 72 } 73 74 @JsonProperty("mywrapped") getWrappedElementProperty()75 public List<String> getWrappedElementProperty() 76 { 77 return wrappedElementProperty; 78 } 79 80 @JsonProperty("mywrapped") setWrappedElementProperty(List<String> wrappedElementProperty)81 public void setWrappedElementProperty(List<String> wrappedElementProperty) 82 { 83 this.wrappedElementProperty = wrappedElementProperty; 84 } 85 getEnumProperty()86 public EnumExample getEnumProperty() 87 { 88 return enumProperty; 89 } 90 setEnumProperty(EnumExample enumProperty)91 public void setEnumProperty(EnumExample enumProperty) 92 { 93 this.enumProperty = enumProperty; 94 } 95 } 96 97 public static class QNameSerializer extends JsonSerializer<QName> { 98 99 @Override serialize(QName value, JsonGenerator jgen, SerializerProvider provider)100 public void serialize(QName value, JsonGenerator jgen, SerializerProvider provider) 101 throws IOException, JsonProcessingException 102 { 103 jgen.writeString(value.toString()); 104 } 105 } 106 107 108 public static class QNameDeserializer extends StdDeserializer<QName> 109 { QNameDeserializer()110 public QNameDeserializer() { super(QName.class); } 111 @Override deserialize(JsonParser jp, DeserializationContext ctxt)112 public QName deserialize(JsonParser jp, DeserializationContext ctxt) 113 throws IOException, JsonProcessingException 114 { 115 return QName.valueOf(jp.readValueAs(String.class)); 116 } 117 } 118 119 public static class DummyBuilder extends StdTypeResolverBuilder 120 //<DummyBuilder> 121 { 122 } 123 124 @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS) 125 @JsonTypeResolver(DummyBuilder.class) 126 static class TypeResolverBean { } 127 128 // @since 1.7 129 @JsonIgnoreType 130 static class IgnoredType { } 131 132 static class IgnoredSubType extends IgnoredType { } 133 134 // Test to ensure we can override enum settings 135 static class LcEnumIntrospector extends JacksonAnnotationIntrospector 136 { 137 private static final long serialVersionUID = 1L; 138 139 @Override findEnumValues(Class<?> enumType, Enum<?>[] enumValues, String[] names)140 public String[] findEnumValues(Class<?> enumType, Enum<?>[] enumValues, String[] names) { 141 // kinda sorta wrong, but for testing's sake... 142 for (int i = 0, len = enumValues.length; i < len; ++i) { 143 names[i] = enumValues[i].name().toLowerCase(); 144 } 145 return names; 146 } 147 } 148 149 /* 150 /********************************************************** 151 /* Unit tests 152 /********************************************************** 153 */ 154 155 /** 156 * tests getting serializer/deserializer instances. 157 */ testSerializeDeserializeWithJaxbAnnotations()158 public void testSerializeDeserializeWithJaxbAnnotations() throws Exception 159 { 160 ObjectMapper mapper = new ObjectMapper(); 161 mapper.enable(SerializationFeature.INDENT_OUTPUT); 162 JacksonExample ex = new JacksonExample(); 163 QName qname = new QName("urn:hi", "hello"); 164 ex.setQname(qname); 165 ex.setAttributeProperty("attributeValue"); 166 ex.setElementProperty("elementValue"); 167 ex.setWrappedElementProperty(Arrays.asList("wrappedElementValue")); 168 ex.setEnumProperty(EnumExample.VALUE1); 169 StringWriter writer = new StringWriter(); 170 mapper.writeValue(writer, ex); 171 writer.flush(); 172 writer.close(); 173 174 String json = writer.toString(); 175 JacksonExample readEx = mapper.readValue(json, JacksonExample.class); 176 177 assertEquals(ex.qname, readEx.qname); 178 assertEquals(ex.attributeProperty, readEx.attributeProperty); 179 assertEquals(ex.elementProperty, readEx.elementProperty); 180 assertEquals(ex.wrappedElementProperty, readEx.wrappedElementProperty); 181 assertEquals(ex.enumProperty, readEx.enumProperty); 182 } 183 testJsonTypeResolver()184 public void testJsonTypeResolver() throws Exception 185 { 186 ObjectMapper mapper = new ObjectMapper(); 187 JacksonAnnotationIntrospector ai = new JacksonAnnotationIntrospector(); 188 AnnotatedClass ac = AnnotatedClassResolver.resolveWithoutSuperTypes(mapper.getSerializationConfig(), 189 TypeResolverBean.class); 190 JavaType baseType = TypeFactory.defaultInstance().constructType(TypeResolverBean.class); 191 TypeResolverBuilder<?> rb = ai.findTypeResolver(mapper.getDeserializationConfig(), ac, baseType); 192 assertNotNull(rb); 193 assertSame(DummyBuilder.class, rb.getClass()); 194 } 195 testEnumHandling()196 public void testEnumHandling() throws Exception 197 { 198 ObjectMapper mapper = new ObjectMapper(); 199 mapper.setAnnotationIntrospector(new LcEnumIntrospector()); 200 assertEquals("\"value1\"", mapper.writeValueAsString(EnumExample.VALUE1)); 201 EnumExample result = mapper.readValue(quote("value1"), EnumExample.class); 202 assertEquals(EnumExample.VALUE1, result); 203 } 204 } 205