• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.ser;
2 
3 import java.io.IOException;
4 import java.util.*;
5 
6 import com.fasterxml.jackson.annotation.*;
7 import com.fasterxml.jackson.core.JsonGenerator;
8 import com.fasterxml.jackson.databind.*;
9 import com.fasterxml.jackson.databind.ser.impl.*;
10 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
11 import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
12 import com.fasterxml.jackson.databind.ser.std.StdSerializer;
13 
14 public class AnyGetterTest extends BaseMapTest
15 {
16     static class Bean
17     {
18         final static Map<String,Boolean> extra = new HashMap<String,Boolean>();
19         static {
20             extra.put("a", Boolean.TRUE);
21         }
22 
getX()23         public int getX() { return 3; }
24 
25         @JsonAnyGetter
getExtra()26         public Map<String,Boolean> getExtra() { return extra; }
27     }
28 
29     static class AnyOnlyBean
30     {
31         @JsonAnyGetter
any()32         public Map<String,Integer> any() {
33             HashMap<String,Integer> map = new HashMap<String,Integer>();
34             map.put("a", 3);
35             return map;
36         }
37     }
38 
39     // For [databind#1376]: allow disabling any-getter
40     static class NotEvenAnyBean extends AnyOnlyBean
41     {
42         @JsonAnyGetter(enabled=false)
43         @Override
any()44         public Map<String,Integer> any() {
45             throw new RuntimeException("Should not get called!)");
46         }
47 
getValue()48         public int getValue() { return 42; }
49     }
50 
51     static class MapAsAny
52     {
53         protected Map<String,Object> stuff = new LinkedHashMap<String,Object>();
54 
55         @JsonAnyGetter
any()56         public Map<String,Object> any() {
57             return stuff;
58         }
59 
add(String key, Object value)60         public void add(String key, Object value) {
61             stuff.put(key, value);
62         }
63     }
64 
65     static class Issue705Bean
66     {
67         protected Map<String,String> stuff;
68 
Issue705Bean(String key, String value)69         public Issue705Bean(String key, String value) {
70             stuff = new LinkedHashMap<String,String>();
71             stuff.put(key, value);
72         }
73 
74         @JsonSerialize(using = Issue705Serializer.class)
75 //    @JsonSerialize(converter = MyConverter.class)
76         @JsonAnyGetter
getParameters()77         public Map<String, String> getParameters(){
78             return stuff;
79         }
80     }
81 
82     @SuppressWarnings("serial")
83     static class Issue705Serializer extends StdSerializer<Object>
84     {
Issue705Serializer()85         public Issue705Serializer() {
86             super(Map.class, false);
87         }
88 
89         @Override
serialize(Object value, JsonGenerator jgen, SerializerProvider provider)90         public void serialize(Object value, JsonGenerator jgen,
91                 SerializerProvider provider) throws IOException
92         {
93             StringBuilder sb = new StringBuilder();
94             for (Map.Entry<?,?> entry : ((Map<?,?>) value).entrySet()) {
95                 sb.append('[').append(entry.getKey()).append('/').append(entry.getValue()).append(']');
96             }
97             jgen.writeStringField("stuff", sb.toString());
98         }
99     }
100 
101     // [databind#1124]
102     static class Bean1124
103     {
104         protected Map<String,String> additionalProperties;
105 
addAdditionalProperty(String key, String value)106         public void addAdditionalProperty(String key, String value) {
107             if (additionalProperties == null) {
108                 additionalProperties = new HashMap<String,String>();
109             }
110             additionalProperties.put(key,value);
111         }
112 
setAdditionalProperties(Map<String, String> additionalProperties)113         public void setAdditionalProperties(Map<String, String> additionalProperties) {
114             this.additionalProperties = additionalProperties;
115         }
116 
117         @JsonAnyGetter
118         @JsonSerialize(contentUsing=MyUCSerializer.class)
getAdditionalProperties()119         public Map<String,String> getAdditionalProperties() { return additionalProperties; }
120     }
121 
122     // [databind#1124]
123     @SuppressWarnings("serial")
124     static class MyUCSerializer extends StdScalarSerializer<String>
125     {
MyUCSerializer()126         public MyUCSerializer() { super(String.class); }
127 
128         @Override
serialize(String value, JsonGenerator gen, SerializerProvider provider)129         public void serialize(String value, JsonGenerator gen,
130                 SerializerProvider provider) throws IOException {
131             gen.writeString(value.toUpperCase());
132         }
133     }
134 
135     static class Bean2592NoAnnotations
136     {
137         protected Map<String, String> properties = new HashMap<>();
138 
139         @JsonAnyGetter
getProperties()140         public Map<String, String> getProperties() {
141             return properties;
142         }
143 
setProperties(Map<String, String> properties)144         public void setProperties(Map<String, String> properties) {
145             this.properties = properties;
146         }
147 
add(String key, String value)148         public void add(String key, String value) {
149             properties.put(key, value);
150         }
151     }
152 
153     static class Bean2592PropertyIncludeNonEmpty extends Bean2592NoAnnotations
154     {
155         @JsonInclude(content = JsonInclude.Include.NON_EMPTY)
156         @JsonAnyGetter
157         @Override
getProperties()158         public Map<String, String> getProperties() {
159             return properties;
160         }
161     }
162 
163     @JsonFilter("Bean2592")
164     static class Bean2592WithFilter extends Bean2592NoAnnotations {}
165 
166     /*
167     /**********************************************************
168     /* Test methods
169     /**********************************************************
170      */
171 
172     private final ObjectMapper MAPPER = new ObjectMapper();
173 
testSimpleAnyBean()174     public void testSimpleAnyBean() throws Exception
175     {
176         String json = MAPPER.writeValueAsString(new Bean());
177         Map<?,?> map = MAPPER.readValue(json, Map.class);
178         assertEquals(2, map.size());
179         assertEquals(Integer.valueOf(3), map.get("x"));
180         assertEquals(Boolean.TRUE, map.get("a"));
181     }
182 
testAnyOnly()183     public void testAnyOnly() throws Exception
184     {
185         ObjectMapper m;
186 
187         // First, with normal fail settings:
188         m = new ObjectMapper();
189         m.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, true);
190         String json = serializeAsString(m, new AnyOnlyBean());
191         assertEquals("{\"a\":3}", json);
192 
193         // then without fail
194         m = new ObjectMapper();
195         m.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
196         json = serializeAsString(m, new AnyOnlyBean());
197         assertEquals("{\"a\":3}", json);
198     }
199 
testAnyDisabling()200     public void testAnyDisabling() throws Exception
201     {
202         String json = MAPPER.writeValueAsString(new NotEvenAnyBean());
203         assertEquals(aposToQuotes("{'value':42}"), json);
204     }
205 
206     // Trying to repro [databind#577]
testAnyWithNull()207     public void testAnyWithNull() throws Exception
208     {
209         MapAsAny input = new MapAsAny();
210         input.add("bar", null);
211         assertEquals(aposToQuotes("{'bar':null}"),
212                 MAPPER.writeValueAsString(input));
213     }
214 
testIssue705()215     public void testIssue705() throws Exception
216     {
217         Issue705Bean input = new Issue705Bean("key", "value");
218         String json = MAPPER.writeValueAsString(input);
219         assertEquals("{\"stuff\":\"[key/value]\"}", json);
220     }
221 
222     // [databind#1124]
testAnyGetterWithValueSerializer()223     public void testAnyGetterWithValueSerializer() throws Exception
224     {
225         ObjectMapper mapper = new ObjectMapper();
226         Bean1124 input = new Bean1124();
227         input.addAdditionalProperty("key", "value");
228         String json = mapper.writeValueAsString(input);
229         assertEquals("{\"key\":\"VALUE\"}", json);
230     }
231 
232     // [databind#2592]
testAnyGetterWithMapperDefaultIncludeNonEmpty()233     public void testAnyGetterWithMapperDefaultIncludeNonEmpty() throws Exception
234     {
235         ObjectMapper mapper = new ObjectMapper()
236                 .setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
237         Bean2592NoAnnotations input = new Bean2592NoAnnotations();
238         input.add("non-empty", "property");
239         input.add("empty", "");
240         input.add("null", null);
241         String json = mapper.writeValueAsString(input);
242         assertEquals("{\"non-empty\":\"property\"}", json);
243     }
244 
245     // [databind#2592]
testAnyGetterWithMapperDefaultIncludeNonEmptyAndFilterOnBean()246     public void testAnyGetterWithMapperDefaultIncludeNonEmptyAndFilterOnBean() throws Exception
247     {
248         FilterProvider filters = new SimpleFilterProvider()
249                 .addFilter("Bean2592", SimpleBeanPropertyFilter.serializeAllExcept("something"));
250         ObjectMapper mapper = new ObjectMapper()
251                 .setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
252                 .setFilterProvider(filters);
253         Bean2592WithFilter input = new Bean2592WithFilter();
254         input.add("non-empty", "property");
255         input.add("empty", "");
256         input.add("null", null);
257         String json = mapper.writeValueAsString(input);
258         // Unfortunately path for bean with filter is different. It still skips nulls.
259         assertEquals("{\"non-empty\":\"property\",\"empty\":\"\"}", json);
260     }
261 
262     // [databind#2592]
testAnyGetterWithPropertyIncludeNonEmpty()263     public void testAnyGetterWithPropertyIncludeNonEmpty() throws Exception
264     {
265         ObjectMapper mapper = new ObjectMapper();
266         Bean2592PropertyIncludeNonEmpty input = new Bean2592PropertyIncludeNonEmpty();
267         input.add("non-empty", "property");
268         input.add("empty", "");
269         input.add("null", null);
270         String json = mapper.writeValueAsString(input);
271         assertEquals("{\"non-empty\":\"property\"}", json);
272     }
273 
274     // [databind#2592]
testAnyGetterConfigIncludeNonEmpty()275     public void testAnyGetterConfigIncludeNonEmpty() throws Exception
276     {
277         ObjectMapper mapper = new ObjectMapper();
278         mapper.configOverride(Map.class).setInclude(JsonInclude.Value.construct(
279                 JsonInclude.Include.USE_DEFAULTS,
280                 JsonInclude.Include.NON_EMPTY
281         ));
282         Bean2592NoAnnotations input = new Bean2592NoAnnotations();
283         input.add("non-empty", "property");
284         input.add("empty", "");
285         input.add("null", null);
286         String json = mapper.writeValueAsString(input);
287         assertEquals("{\"non-empty\":\"property\"}", json);
288     }
289 }
290