1 package com.fasterxml.jackson.databind.ser; 2 3 import java.util.*; 4 5 import com.fasterxml.jackson.annotation.JsonInclude; 6 import com.fasterxml.jackson.core.JsonGenerator; 7 import com.fasterxml.jackson.databind.*; 8 import com.fasterxml.jackson.databind.annotation.JsonAppend; 9 import com.fasterxml.jackson.databind.cfg.MapperConfig; 10 import com.fasterxml.jackson.databind.introspect.AnnotatedClass; 11 import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; 12 import com.fasterxml.jackson.databind.util.Annotations; 13 14 /** 15 * Tests for verifying that one can append virtual properties after regular ones. 16 * 17 * @since 2.5 18 */ 19 public class TestVirtualProperties extends BaseMapTest 20 { 21 @JsonAppend(attrs={ @JsonAppend.Attr("id"), 22 @JsonAppend.Attr(value="internal", propName="extra", required=true) 23 }) 24 static class SimpleBean 25 { 26 public int value = 13; 27 } 28 29 @JsonAppend(prepend=true, attrs={ @JsonAppend.Attr("id"), 30 @JsonAppend.Attr(value="internal", propName="extra") 31 }) 32 static class SimpleBeanPrepend 33 { 34 public int value = 13; 35 } 36 37 enum ABC { 38 A, B, C; 39 } 40 41 @JsonAppend(attrs=@JsonAppend.Attr(value="desc", include=JsonInclude.Include.NON_EMPTY)) 42 static class OptionalsBean 43 { 44 public int value = 28; 45 } 46 47 @SuppressWarnings("serial") 48 static class CustomVProperty 49 extends VirtualBeanPropertyWriter 50 { CustomVProperty()51 private CustomVProperty() { super(); } 52 CustomVProperty(BeanPropertyDefinition propDef, Annotations ctxtAnn, JavaType type)53 private CustomVProperty(BeanPropertyDefinition propDef, 54 Annotations ctxtAnn, JavaType type) { 55 super(propDef, ctxtAnn, type); 56 } 57 58 @Override value(Object bean, JsonGenerator jgen, SerializerProvider prov)59 protected Object value(Object bean, JsonGenerator jgen, SerializerProvider prov) { 60 if (_name.toString().equals("id")) { 61 return "abc123"; 62 } 63 if (_name.toString().equals("extra")) { 64 return new int[] { 42 }; 65 } 66 return "???"; 67 } 68 69 @Override withConfig(MapperConfig<?> config, AnnotatedClass declaringClass, BeanPropertyDefinition propDef, JavaType type)70 public VirtualBeanPropertyWriter withConfig(MapperConfig<?> config, 71 AnnotatedClass declaringClass, BeanPropertyDefinition propDef, 72 JavaType type) 73 { 74 return new CustomVProperty(propDef, declaringClass.getAnnotations(), type); 75 } 76 } 77 78 @JsonAppend(prepend=true, props={ @JsonAppend.Prop(value=CustomVProperty.class, name="id"), 79 @JsonAppend.Prop(value=CustomVProperty.class, name="extra") 80 }) 81 static class CustomVBean 82 { 83 public int value = 72; 84 } 85 86 /* 87 /********************************************************** 88 /* Test methods 89 /********************************************************** 90 */ 91 92 private final ObjectWriter WRITER = objectWriter(); 93 testAttributeProperties()94 public void testAttributeProperties() throws Exception 95 { 96 Map<String,Object> stuff = new LinkedHashMap<String,Object>(); 97 stuff.put("x", 3); 98 stuff.put("y", ABC.B); 99 100 String json = WRITER.withAttribute("id", "abc123") 101 .withAttribute("internal", stuff) 102 .writeValueAsString(new SimpleBean()); 103 assertEquals(aposToQuotes("{'value':13,'id':'abc123','extra':{'x':3,'y':'B'}}"), json); 104 105 json = WRITER.withAttribute("id", "abc123") 106 .withAttribute("internal", stuff) 107 .writeValueAsString(new SimpleBeanPrepend()); 108 assertEquals(aposToQuotes("{'id':'abc123','extra':{'x':3,'y':'B'},'value':13}"), json); 109 } 110 testAttributePropInclusion()111 public void testAttributePropInclusion() throws Exception 112 { 113 // first, with desc 114 String json = WRITER.withAttribute("desc", "nice") 115 .writeValueAsString(new OptionalsBean()); 116 assertEquals(aposToQuotes("{'value':28,'desc':'nice'}"), json); 117 118 // then with null (not defined) 119 json = WRITER.writeValueAsString(new OptionalsBean()); 120 assertEquals(aposToQuotes("{'value':28}"), json); 121 122 // and finally "empty" 123 json = WRITER.withAttribute("desc", "") 124 .writeValueAsString(new OptionalsBean()); 125 assertEquals(aposToQuotes("{'value':28}"), json); 126 } 127 testCustomProperties()128 public void testCustomProperties() throws Exception 129 { 130 String json = WRITER.withAttribute("desc", "nice") 131 .writeValueAsString(new CustomVBean()); 132 assertEquals(aposToQuotes("{'id':'abc123','extra':[42],'value':72}"), json); 133 } 134 } 135