• 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.JsonAnyGetter;
7 import com.fasterxml.jackson.annotation.JsonValue;
8 
9 import com.fasterxml.jackson.core.JsonGenerator;
10 
11 import com.fasterxml.jackson.databind.*;
12 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
13 
14 public class EnumAsMapKeyTest extends BaseMapTest
15 {
16     static class MapBean {
17         public Map<ABCEnum,Integer> map = new HashMap<>();
18 
add(ABCEnum key, int value)19         public void add(ABCEnum key, int value) {
20             map.put(key, Integer.valueOf(value));
21         }
22     }
23 
24     protected enum ABCEnum {
25         A, B, C;
ABCEnum()26         private ABCEnum() { }
27 
toString()28         @Override public String toString() { return name().toLowerCase(); }
29     }
30 
31     // [databind#594]
32     static enum MyEnum594 {
33         VALUE_WITH_A_REALLY_LONG_NAME_HERE("longValue");
34 
35         private final String key;
MyEnum594(String k)36         private MyEnum594(String k) { key = k; }
37 
38         @JsonValue
getKey()39         public String getKey() { return key; }
40     }
41 
42     static class MyStuff594 {
43         public Map<MyEnum594,String> stuff = new EnumMap<MyEnum594,String>(MyEnum594.class);
44 
MyStuff594(String value)45         public MyStuff594(String value) {
46             stuff.put(MyEnum594.VALUE_WITH_A_REALLY_LONG_NAME_HERE, value);
47         }
48     }
49 
50     // [databind#661]
51     static class MyBean661 {
52         private Map<Foo661, String> foo = new EnumMap<Foo661, String>(Foo661.class);
53 
MyBean661(String value)54         public MyBean661(String value) {
55             foo.put(Foo661.FOO, value);
56         }
57 
58         @JsonAnyGetter
59         @JsonSerialize(keyUsing = Foo661.Serializer.class)
getFoo()60         public Map<Foo661, String> getFoo() {
61             return foo;
62         }
63     }
64 
65     enum Foo661 {
66         FOO;
67         public static class Serializer extends JsonSerializer<Foo661> {
68             @Override
serialize(Foo661 value, JsonGenerator jgen, SerializerProvider provider)69             public void serialize(Foo661 value, JsonGenerator jgen, SerializerProvider provider)
70                     throws IOException {
71                 jgen.writeFieldName("X-"+value.name());
72             }
73         }
74     }
75 
76     // [databind#2129]
77     public enum Type {
78         FIRST,
79         SECOND;
80     }
81 
82     static class TypeContainer {
83         public Map<Type, Integer> values;
84 
TypeContainer(Type type, int value)85         public TypeContainer(Type type, int value) {
86             values = Collections.singletonMap(type, value);
87         }
88     }
89 
90     /*
91     /**********************************************************************
92     /* Test methods
93     /**********************************************************************
94      */
95 
96     private final ObjectMapper MAPPER = newJsonMapper();
97 
testMapWithEnumKeys()98     public void testMapWithEnumKeys() throws Exception
99     {
100         MapBean bean = new MapBean();
101         bean.add(ABCEnum.B, 3);
102 
103         // By default Enums serialized using `name()`
104         String json = MAPPER.writeValueAsString(bean);
105         assertEquals("{\"map\":{\"B\":3}}", json);
106 
107         // but can change
108         json = MAPPER.writer()
109                 .with(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
110                 .writeValueAsString(bean);
111         assertEquals("{\"map\":{\"b\":3}}", json);
112 
113         // [databind#1570]
114 
115         // 14-Sep-2019, tatu: as per [databind#2129], must NOT use this feature but
116         //    instead new `WRITE_ENUM_KEYS_USING_INDEX` added in 2.10
117         json = MAPPER.writer()
118                 .with(SerializationFeature.WRITE_ENUMS_USING_INDEX)
119                 .writeValueAsString(bean);
120 //        assertEquals(aposToQuotes("{'map':{'"+TestEnum.B.ordinal()+"':3}}"), json);
121         assertEquals(aposToQuotes("{'map':{'B':3}}"), json);
122     }
123 
testCustomEnumMapKeySerializer()124     public void testCustomEnumMapKeySerializer() throws Exception {
125         String json = MAPPER.writeValueAsString(new MyBean661("abc"));
126         assertEquals(aposToQuotes("{'X-FOO':'abc'}"), json);
127     }
128 
129     // [databind#594]
testJsonValueForEnumMapKey()130     public void testJsonValueForEnumMapKey() throws Exception {
131         assertEquals(aposToQuotes("{'stuff':{'longValue':'foo'}}"),
132                 MAPPER.writeValueAsString(new MyStuff594("foo")));
133     }
134 
135     // [databind#2129]
testEnumAsIndexForRootMap()136     public void testEnumAsIndexForRootMap() throws Exception
137     {
138         final Map<Type, Integer> input = Collections.singletonMap(Type.FIRST, 3);
139 
140         // by default, write using name()
141         assertEquals(aposToQuotes("{'FIRST':3}"),
142                 MAPPER.writeValueAsString(input));
143 
144         // but change with setting
145         assertEquals(aposToQuotes("{'0':3}"),
146                 MAPPER.writer()
147                 .with(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX)
148                 .writeValueAsString(input));
149 
150         // but NOT with value settings
151         assertEquals(aposToQuotes("{'FIRST':3}"),
152                 MAPPER.writer()
153                     .with(SerializationFeature.WRITE_ENUMS_USING_INDEX)
154                     .writeValueAsString(input));
155     }
156 
157     // [databind#2129]
testEnumAsIndexForValueMap()158     public void testEnumAsIndexForValueMap() throws Exception
159     {
160         final TypeContainer input = new TypeContainer(Type.SECOND, 72);
161 
162         // by default, write using name()
163         assertEquals(aposToQuotes("{'values':{'SECOND':72}}"),
164                 MAPPER.writeValueAsString(input));
165 
166         // but change with setting
167         assertEquals(aposToQuotes("{'values':{'1':72}}"),
168                 MAPPER.writer()
169                 .with(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX)
170                 .writeValueAsString(input));
171 
172         // but NOT with value settings
173         assertEquals(aposToQuotes("{'values':{'SECOND':72}}"),
174                 MAPPER.writer()
175                     .with(SerializationFeature.WRITE_ENUMS_USING_INDEX)
176                     .writeValueAsString(input));
177     }
178 }
179