Skip to content

Commit b9c1ada

Browse files
committed
Fix #2503 (support keyUsing on key class)
1 parent 416d72d commit b9c1ada

18 files changed

+99
-32
lines changed

release-notes/VERSION-2.x

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Project: jackson-databind
88

99
#2487: BeanDeserializerBuilder Protected Factory Method for Extension
1010
(contributed by Ville K)
11+
#2503: Support `@JsonSerialize(keyUsing)` and `@JsonDeserialize(keyUsing)` on Key class
1112

1213
2.10.1 (not yet released)
1314

src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,7 @@ public TypeSerializer findTypeSerializer(JavaType javaType) throws JsonMappingEx
791791
public JsonSerializer<Object> findKeySerializer(JavaType keyType, BeanProperty property)
792792
throws JsonMappingException
793793
{
794-
JsonSerializer<Object> ser = _serializerFactory.createKeySerializer(_config, keyType, _keySerializer);
794+
JsonSerializer<Object> ser = _serializerFactory.createKeySerializer(this, keyType, _keySerializer);
795795
// 25-Feb-2011, tatu: As per [JACKSON-519], need to ensure contextuality works here, too
796796
return _handleContextualResolvable(ser, property);
797797
}

src/main/java/com/fasterxml/jackson/databind/node/BigIntegerNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
/**
1111
* Numeric node that contains simple 64-bit integer values.
1212
*/
13+
@SuppressWarnings("serial")
1314
public class BigIntegerNode
1415
extends NumericNode
1516
{

src/main/java/com/fasterxml/jackson/databind/node/DecimalNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* Numeric node that contains values that do not fit in simple
1212
* integer (int, long) or floating point (double) values.
1313
*/
14+
@SuppressWarnings("serial")
1415
public class DecimalNode
1516
extends NumericNode
1617
{

src/main/java/com/fasterxml/jackson/databind/node/DoubleNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* Numeric node that contains 64-bit ("double precision")
1414
* floating point values simple 32-bit integer values.
1515
*/
16+
@SuppressWarnings("serial")
1617
public class DoubleNode
1718
extends NumericNode
1819
{

src/main/java/com/fasterxml/jackson/databind/node/FloatNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*
1515
* @since 2.2
1616
*/
17+
@SuppressWarnings("serial")
1718
public class FloatNode extends NumericNode
1819
{
1920
protected final float _value;

src/main/java/com/fasterxml/jackson/databind/node/IntNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
/**
1313
* Numeric node that contains simple 32-bit integer values.
1414
*/
15+
@SuppressWarnings("serial")
1516
public class IntNode
1617
extends NumericNode
1718
{

src/main/java/com/fasterxml/jackson/databind/node/LongNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
/**
1313
* Numeric node that contains simple 64-bit integer values.
1414
*/
15+
@SuppressWarnings("serial")
1516
public class LongNode
1617
extends NumericNode
1718
{

src/main/java/com/fasterxml/jackson/databind/node/ShortNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
/**
1313
* Numeric node that contains simple 16-bit integer values.
1414
*/
15+
@SuppressWarnings("serial")
1516
public class ShortNode
1617
extends NumericNode
1718
{

src/main/java/com/fasterxml/jackson/databind/ser/BasicSerializerFactory.java

Lines changed: 76 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -198,14 +198,15 @@ public abstract JsonSerializer<Object> createSerializer(SerializerProvider prov,
198198
JavaType type)
199199
throws JsonMappingException;
200200

201-
@Override
201+
@Override // since 2.11
202202
@SuppressWarnings("unchecked")
203-
public JsonSerializer<Object> createKeySerializer(SerializationConfig config,
204-
JavaType keyType, JsonSerializer<Object> defaultImpl)
203+
public JsonSerializer<Object> createKeySerializer(SerializerProvider prov,
204+
JavaType keyType, JsonSerializer<Object> defaultImpl) throws JsonMappingException
205205
{
206-
// We should not need any member method info; at most class annotations for Map type
207-
// ... at least, not here.
208-
BeanDescription beanDesc = config.introspectClassAnnotations(keyType.getRawClass());
206+
// 16-Oct-2019, tatu: use to only introspect class annotations but we'll
207+
// need methods too for `@JsonValue` later; and custom lookup might want it, too
208+
final SerializationConfig config = prov.getConfig();
209+
BeanDescription beanDesc = config.introspect(keyType);
209210
JsonSerializer<?> ser = null;
210211
// Minor optimization: to avoid constructing beanDesc, bail out if none registered
211212
if (_factoryConfig.hasKeySerializers()) {
@@ -218,29 +219,34 @@ public JsonSerializer<Object> createKeySerializer(SerializationConfig config,
218219
}
219220
}
220221
if (ser == null) {
221-
ser = defaultImpl;
222+
// [databind#2452]: Support `@JsonSerialize(keyUsing = ...)` -- new in 2.11
223+
if (prov != null) {
224+
ser = _findKeySerializer(prov, beanDesc.getClassInfo());
225+
}
222226
if (ser == null) {
223-
ser = StdKeySerializers.getStdKeySerializer(config, keyType.getRawClass(), false);
224-
// As per [databind#47], also need to support @JsonValue
227+
ser = defaultImpl;
225228
if (ser == null) {
226-
beanDesc = config.introspect(keyType);
227-
AnnotatedMember am = beanDesc.findJsonValueAccessor();
228-
if (am != null) {
229-
final Class<?> rawType = am.getRawType();
230-
JsonSerializer<?> delegate = StdKeySerializers.getStdKeySerializer(config,
231-
rawType, true);
232-
if (config.canOverrideAccessModifiers()) {
233-
ClassUtil.checkAndFixAccess(am.getMember(),
234-
config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
229+
ser = StdKeySerializers.getStdKeySerializer(config, keyType.getRawClass(), false);
230+
// As per [databind#47], also need to support @JsonValue
231+
if (ser == null) {
232+
AnnotatedMember am = beanDesc.findJsonValueAccessor();
233+
if (am != null) {
234+
final Class<?> rawType = am.getRawType();
235+
JsonSerializer<?> delegate = StdKeySerializers.getStdKeySerializer(config,
236+
rawType, true);
237+
if (config.canOverrideAccessModifiers()) {
238+
ClassUtil.checkAndFixAccess(am.getMember(),
239+
config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
240+
}
241+
ser = new JsonValueSerializer(am, delegate);
242+
} else {
243+
ser = StdKeySerializers.getFallbackKeySerializer(config, keyType.getRawClass());
235244
}
236-
ser = new JsonValueSerializer(am, delegate);
237-
} else {
238-
ser = StdKeySerializers.getFallbackKeySerializer(config, keyType.getRawClass());
239245
}
240246
}
241247
}
242248
}
243-
249+
244250
// [databind#120]: Allow post-processing
245251
if (_factoryConfig.hasSerializerModifiers()) {
246252
for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
@@ -250,6 +256,54 @@ public JsonSerializer<Object> createKeySerializer(SerializationConfig config,
250256
return (JsonSerializer<Object>) ser;
251257
}
252258

259+
// Old method: to be removed from 3.0 -- similar to above but can't look for "keyUsing"
260+
@Override
261+
@SuppressWarnings("unchecked")
262+
@Deprecated // since 2.11
263+
public JsonSerializer<Object> createKeySerializer(SerializationConfig config,
264+
JavaType keyType, JsonSerializer<Object> defaultImpl)
265+
{
266+
BeanDescription beanDesc = config.introspect(keyType);
267+
JsonSerializer<?> ser = null;
268+
if (_factoryConfig.hasKeySerializers()) {
269+
for (Serializers serializers : _factoryConfig.keySerializers()) {
270+
ser = serializers.findSerializer(config, keyType, beanDesc);
271+
if (ser != null) {
272+
break;
273+
}
274+
}
275+
}
276+
if (ser == null) {
277+
if (ser == null) {
278+
ser = defaultImpl;
279+
if (ser == null) {
280+
ser = StdKeySerializers.getStdKeySerializer(config, keyType.getRawClass(), false);
281+
if (ser == null) {
282+
AnnotatedMember am = beanDesc.findJsonValueAccessor();
283+
if (am != null) {
284+
final Class<?> rawType = am.getRawType();
285+
JsonSerializer<?> delegate = StdKeySerializers.getStdKeySerializer(config,
286+
rawType, true);
287+
if (config.canOverrideAccessModifiers()) {
288+
ClassUtil.checkAndFixAccess(am.getMember(),
289+
config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
290+
}
291+
ser = new JsonValueSerializer(am, delegate);
292+
} else {
293+
ser = StdKeySerializers.getFallbackKeySerializer(config, keyType.getRawClass());
294+
}
295+
}
296+
}
297+
}
298+
}
299+
if (_factoryConfig.hasSerializerModifiers()) {
300+
for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
301+
ser = mod.modifyKeySerializer(config, keyType, beanDesc, ser);
302+
}
303+
}
304+
return (JsonSerializer<Object>) ser;
305+
}
306+
253307
/**
254308
* Method called to construct a type serializer for values with given declared
255309
* base type. This is called for values other than those of bean property

src/main/java/com/fasterxml/jackson/databind/ser/SerializerFactory.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,16 @@ public abstract TypeSerializer createTypeSerializer(SerializationConfig config,
7878
*
7979
* @return Serializer to use, if factory knows it; null if not (in which case default
8080
* serializer is to be used)
81+
*
82+
* @since 2.11
8183
*/
84+
public JsonSerializer<Object> createKeySerializer(SerializerProvider prov,
85+
JavaType type, JsonSerializer<Object> defaultImpl)
86+
throws JsonMappingException {
87+
return createKeySerializer(prov.getConfig(), type, defaultImpl);
88+
}
89+
90+
@Deprecated // since 2.11
8291
public abstract JsonSerializer<Object> createKeySerializer(SerializationConfig config,
8392
JavaType type, JsonSerializer<Object> defaultImpl)
8493
throws JsonMappingException;

src/main/java/com/fasterxml/jackson/databind/type/PlaceholderForType.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ public JavaType refine(Class<?> rawType, TypeBindings bindings, JavaType superCl
8383
return _unsupported();
8484
}
8585

86-
@SuppressWarnings("deprecation")
8786
@Override
8887
protected JavaType _narrow(Class<?> subclass) {
8988
return _unsupported();

src/test/java/com/fasterxml/jackson/databind/deser/jdk/CustomMapKeys2454Test.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ public Object deserializeKey(String key, DeserializationContext ctxt) {
2929
}
3030
}
3131

32-
static class Key2454Serializer extends JsonSerializer<String> {
32+
static class Key2454Serializer extends JsonSerializer<Key2454> {
3333
@Override
34-
public void serialize(String value, JsonGenerator gen,
34+
public void serialize(Key2454 value, JsonGenerator gen,
3535
SerializerProvider serializers) throws IOException {
36-
gen.writeFieldName("id="+value);
36+
gen.writeFieldName("id="+value.id);
3737
}
3838
}
3939

@@ -42,7 +42,7 @@ public void serialize(String value, JsonGenerator gen,
4242
public void testCustomSerializer() throws Exception
4343
{
4444
assertEquals(aposToQuotes("{'id=a':'b'}"),
45-
MAPPER.writeValueAsString(Collections.singletonMap("a", "b")));
45+
MAPPER.writeValueAsString(Collections.singletonMap(new Key2454("a", true), "b")));
4646
}
4747

4848
public void testCustomDeserializer() throws Exception

src/test/java/com/fasterxml/jackson/databind/format/MapFormatShapeTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.fasterxml.jackson.databind.format;
22

33
import java.util.Collection;
4-
import java.util.HashMap;
54
import java.util.LinkedHashMap;
65
import java.util.Map;
76
import java.util.Set;

src/test/java/com/fasterxml/jackson/databind/jsontype/GenericNestedType2331Test.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public List<? extends SuperNode<Node<T>>> getChildren() {
3030
}
3131
}
3232

33+
@SuppressWarnings("rawtypes")
3334
public void testGeneric2331() throws Exception {
3435
Node root = new Node();
3536
root.children.add(new Node());

src/test/java/com/fasterxml/jackson/databind/mixins/MapperMixinsCopy1998Test.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ public MyChildB(String name) {
8888
}
8989
}
9090

91-
@SuppressWarnings("deprecation")
9291
public void testB_KO() throws Exception
9392
{
9493
final ObjectMapper DEFAULT = defaultMapper();

src/test/java/com/fasterxml/jackson/databind/module/TestDuplicateRegistration.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ public void setupModule(SetupContext context) {
2828
}
2929
}
3030

31-
@SuppressWarnings("deprecation")
3231
public void testDuplicateRegistration() throws Exception
3332
{
3433
// by default, duplicate registration should be prevented

src/test/java/com/fasterxml/jackson/databind/ser/TestRootType.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
1111

1212
import com.fasterxml.jackson.databind.*;
13-
import com.fasterxml.jackson.databind.json.JsonMapper;
1413
import com.fasterxml.jackson.databind.type.TypeFactory;
1514

1615
/**

0 commit comments

Comments
 (0)